November 17, 2005 at 11:54 am
I would like to take the results of an sql statement that are returned horizontally and place them in a vertical order. For example,
SELECT Top 1 LastName, FirstName, Gender, Age
FROM Client
The standard results would look something like:
LastName FirstName Gender Age
Smith Joe M 32
Is there a way, without using a cursor where the results could instead be displayed as:
FieldName Value
LastName Smith
FirstName Joe
Gender M
Age 32
This really should be a function that will accept a recordset with a variety of possible column headers. One recordset may have 4 columns and another may have 10, but all would return only one data record.
I have tried using syscolumns, but haven't been able to get it to work.
Thanks,
Keoki
November 17, 2005 at 12:54 pm
I am using the SQL Server 2005 CTP and it has some nice new TSQL features like PIVOT and UNPIVOT which take care of this very nicely. However, I have not found a way to do this within SQL Server 2000 or earlier. When I have really needed to do this I ended up creating a pivot table in Excel using a data link to SQL Server and doing it that way.
November 17, 2005 at 2:37 pm
Unfortunatelly you have to perform a union
Select 'First Name' as FieldName, FirstName as Value
From mytable
where id = 1
union
Select 'Last Name', LastName
From mytable
where id = 1
Select 'Gender', Gender
From mytable
where id = 1
Select 'Age', Age
From mytable
where id = 1
November 19, 2005 at 2:29 pm
Does this work for you?
USE tempdb
IF OBJECTPROPERTY(OBJECT_ID('dbo.MyPivot'), 'IsUserTable') = 1
DROP TABLE dbo.MyPivot;
GO
CREATE TABLE dbo.MyPivot
(
ID INT NOT NULL
, LastName VARCHAR(20) NOT NULL
, FirstName VARCHAR(20) NOT NULL
, Gender CHAR(1) NOT NULL
, Age TINYINT NOT NULL
);
GO
INSERT INTO MyPivot VALUES (1, 'Smith','Joe','M',32)
INSERT INTO MyPivot VALUES (2, 'Baker','Mary','F',26)
CREATE TABLE dbo.#MySchema
(
objectid INT NOT NULL,
attribute NVARCHAR(30) NOT NULL
PRIMARY KEY (objectid, attribute)
);
GO
-- This assumes the ID is Ordinal_Position = 1 and isn't required in the output
INSERT INTO dbo.#MySchema
SELECT Ordinal_Position, Column_Name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_Name='MyPivot' AND Ordinal_Position > 1 ;
GO
SELECT attribute, MyValue =
CASE attribute
WHEN 'LastName' THEN CAST(LastName as SQL_VARIANT)
WHEN 'FirstName' THEN CAST(FirstName as SQL_VARIANT)
WHEN 'Gender' THEN CAST(Gender as SQL_VARIANT)
WHEN 'Age' THEN CAST(Age as SQL_VARIANT)
END
FROM #MySchema CROSS JOIN MyPivot
ORDER BY ID, Objectid
DROP TABLE dbo.#MySchema;
November 21, 2005 at 8:38 am
That would work except for the fact that it needs to be dynamic. It is quite possible the names and number of columns to be converted would be different from one run to the next.
November 21, 2005 at 9:08 am
i searched for "pivot" here on SSC, and found a number of script contributions; you should look at those as well;
this link looked promising: http://www.sqlservercentral.com/scripts/contributions/1038.asp
Lowell
November 21, 2005 at 5:45 pm
I have added the dynamic element you need, hopefully this will be closer to what you need.
Youwill need to know the name of the field which uniquely identifies each row in the input table or view.
USE Tempdb
GO
--Create the Data
IF OBJECTPROPERTY(OBJECT_ID('dbo.MyData'), 'IsUserTable') = 1
DROP TABLE dbo.MyData;
GO
CREATE TABLE dbo.MyData
(
ID INT NOT NULL
, LastName VARCHAR(20) NOT NULL
, FirstName VARCHAR(20) NOT NULL
, Gender CHAR(1) NOT NULL
, Age TINYINT NOT NULL
);
GO
INSERT INTO MyData VALUES (1, 'Smith','Joe','M',32)
INSERT INTO MyData VALUES (2, 'Baker','Mary','F',26)
GO
-- Create stored proc which will create the pivoted table
-- Input Parameters
-- 1 name of the table or view containing the data
-- 2 Field Name which will uniquely identify each row in table or view(only 1 in this example)
-- 3 name of the output table
CREATE PROC #usp_Pivot
(
@Table VARCHAR(40)
, @ID VARCHAR(40)
, @Pivot VARCHAR(40)
) AS
DECLARE
@Sql varchar(8000)
, @Cnt int
, @Max int
IF OBJECTPROPERTY(OBJECT_ID('MyPivot'), 'IsUserTable') = 1
EXECUTE ('DROP TABLE ' + @Pivot )
CREATE TABLE dbo.#MySchema
(
objectid INT NOT NULL,
attribute NVARCHAR(30) NOT NULL
PRIMARY KEY (objectid, attribute)
-- Timmestamp cannot be converted to string so is excluded, maybe others?
INSERT INTO dbo.#MySchema
SELECT Ordinal_Position, Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_Name = @Table AND data_type <> 'TIMESTAMP'
SET @Max = (SELECT COUNT(*) FROM #MySchema)
SET @Cnt = 1
SET @Sql = 'SELECT ' + @ID + ' , attribute, MyValue =
CASE objectid'
WHILE @Cnt < @max-2 + 1
BEGIN
SET @sql = @sql + ' WHEN ' + CAST(@Cnt AS char(3)) + ' THEN CAST('
SET @sql = @sql + (SELECT attribute FROM #MySchema WHERE objectid = @Cnt)
SET @sql = @sql + ' as SQL_VARIANT) '
SET @Cnt = @Cnt + 1
END
INTO ' + @Pivot + '
FROM #MySchema CROSS JOIN ' + @Table + '
ORDER BY ' + @ID + ' , objectid;'
EXECUTE (@Sql);
DROP TABLE dbo.#MySchema;
GO
-- End Stored proc creation
-- Run the stored proc
EXEC #usp_Pivot 'MyData','ID','MyPivot'
DROP PROCEDURE #usp_Pivot
-- display the pivot info
SELECT * FROM MyPivot
November 21, 2005 at 8:22 pm
Sorry small error, left in the literal 'MyPivot' instead of @Pivot.
USE Tempdb
GO
--Create the Data
IF OBJECTPROPERTY(OBJECT_ID('dbo.MyData'), 'IsUserTable') = 1
DROP TABLE dbo.MyData;
GO
CREATE TABLE dbo.MyData
(
ID INT NOT NULL
, LastName VARCHAR(20) NOT NULL
, FirstName VARCHAR(20) NOT NULL
, Gender CHAR(1) NOT NULL
, Age TINYINT NOT NULL
);
GO
INSERT INTO MyData VALUES (1, 'Smith','Joe','M',32)
INSERT INTO MyData VALUES (2, 'Baker','Mary','F',26)
GO
-- Create stored proc which will create the pivoted table
-- Input Parameters
-- 1 name of the table or view containing the data
-- 2 Field Name which will uniquely identify each row in table or view(only 1 in this example)
-- 3 name of the output table
CREATE PROC #usp_Pivot
(
@Table VARCHAR(40)
, @ID VARCHAR(40)
, @Pivot VARCHAR(40)
) AS
DECLARE
@Sql varchar(8000)
, @Cnt int
, @Max int
IF OBJECTPROPERTY(OBJECT_ID(@Pivot), 'IsUserTable') = 1
EXECUTE ('DROP TABLE ' + @Pivot )
CREATE TABLE dbo.#MySchema
(
objectid INT NOT NULL,
attribute NVARCHAR(30) NOT NULL
PRIMARY KEY (objectid, attribute)
-- Timmestamp cannot be converted to string so is excluded, maybe others?
INSERT INTO dbo.#MySchema
SELECT Ordinal_Position, Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_Name = @Table AND data_type <> 'TIMESTAMP'
SET @Max = (SELECT COUNT(*) FROM #MySchema)
SET @Cnt = 1
SET @Sql = 'SELECT ' + @ID + ' , attribute, MyValue =
CASE objectid'
WHILE @Cnt < @max-2 + 1
BEGIN
SET @sql = @sql + ' WHEN ' + CAST(@Cnt AS char(3)) + ' THEN CAST('
SET @sql = @sql + (SELECT attribute FROM #MySchema WHERE objectid = @Cnt)
SET @sql = @sql + ' as SQL_VARIANT) '
SET @Cnt = @Cnt + 1
END
INTO ' + @Pivot + '
FROM #MySchema CROSS JOIN ' + @Table + '
ORDER BY ' + @ID + ' , objectid;'
EXECUTE (@Sql);
DROP TABLE dbo.#MySchema;
GO
-- End Stored proc creation
-- Run the stored proc
EXEC #usp_Pivot 'MyData','ID','MyPivot'
DROP PROCEDURE #usp_Pivot
-- display the pivot info
SELECT * FROM MyPivot
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply