I have the following table where I need to transform Columns to Rows
tbl_Survey:
SurveyID Quest_1 Quest_2 Quest_3 7 1 1 1 8 2 2 2 9 3 3 3
I need to have the following result:
SurveyID Questions Rating 7 Quest_1 1 7 Quest_2 1 7 Quest_3 1 8 Quest_1 2 8 Quest_2 2 8 Quest_3 2 9 Quest_1 3 9 Quest_2 3 9 Quest_3 3
To have this result I used the following code:
SELECT [SurveyID], [Question], [Rating] FROM [dbo].[tbl_Survey] UNPIVOT ( [Rating] FOR [Question] in ([Quest_1], [Quest_2], [Quest_3]) ) AS SurveyUnpivot
But, my Quest_1, Quest_2, Quest_3 values could potentially be changed / or even added a new once…
Are there ways to code them, so it can be used for any text values (not only for Quest_1 2 3)? Not necessary with the UNPIVOT… Could be any other way
Thank you
Advertisement
Answer
You need to make a dynamic UNPIVOT
. Check the example below:
DROP TABLE IF EXISTS [dbo].[DataSource]; CREATE TABLE [dbo].[DataSource] ( [SurveyID] INT ,[Quest_1] INT ,[Quest_2] INT ,[Quest_3] INT ); INSERT INTO [dbo].[DataSource] ([SurveyID], [Quest_1], [Quest_2], [Quest_3]) VALUES (7, 1, 1, 1) ,(8, 2, 2, 2) ,(9, 3, 3, 3); GO DECLARE @DynamicTSQLStatement NVARCHAR(MAX); DECLARE @DynamicTSQLUnpivotColumns NVARCHAR(MAX); SET @DynamicTSQLUnpivotColumns = STUFF ( ( SELECT ',' + QUOTENAME([name]) FROM [sys].[columns] WHERE [object_id] = OBJECT_ID('[dbo].[DataSource]') AND [name] <> 'SurveyID' ORDER BY [name] FOR XML PATH(''), TYPE ).value('.', 'VARCHAR(MAX)') ,1 ,1 ,'' ); SET @DynamicTSQLStatement = N' SELECT [SurveyID], [Question], [Rating] FROM [dbo].[DataSource] UNPIVOT ( [Rating] FOR [Question] in (' + @DynamicTSQLUnpivotColumns + ') ) AS SurveyUnpivot'; EXEC sp_executesql @DynamicTSQLStatement;