Forum Discussion
VBA_ENTHU1988
Oct 11, 2024Copper Contributor
Dynamic Pivot in SQL Query without DECLARE
- I have a custom/dynamic SQL to PIVOT column values.
 - As number of Columns are not fixed it could increase or decrease we cannot have normal PIVOT .
 - Instead we need to identify columns dynamically and prepare a dynamic SQL as well.
 - COLUMN_NAME and COLUMN_VALUE needs to be PIVOTED number of rows in these 02 columns may increase decrease on each day run.
 - Posting dummy data as main data cannot be posted.
 - This query works great on database
 - but since our Reporting Tool like Tableau etc. cannot support advance SQL like dynamic or DECLARE keywords
 - Hence is there a way to do the same thing without DECLARE like getting Columns list (comma separated) in CTE with STRING_AGG or something
 - Kindly help me writing PIVOT which pivots columns dynamically without DECLARE
 
USE [DBOOO];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE TABLE [SA0067].[UNPIVOT] (
[RECORD_ID] int NULL,
[METRIC_NAME] varchar(255) NULL,
[NAME] varchar(255) NULL,
[COLUMN_Name] nvarchar(4000) NULL,
[COLUMN_VALUE] nvarchar(255) NULL)
)
;
GO
 ----INSERT statement
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (1,'ABC','AJ','ID',1);
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (2,'ABC','AK','ID',6);
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (3,'XYZ','RJ','ID',4);
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (4,'XYZ','JK','ID',5);
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (5,'XYZ','JJJ','ID',11);
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (6,'REC','MJ','ID',42;
INSERT INTO [SA0067].[UNPIVOT] ([RECORD_ID],[METRIC_NAME],[NAME],[COLUMN_Name],[COLUMN_VALUE] ) VALUES (7,'REC','SG','ID',33);
--- DYNAMIC SQL thats needs to be re-written
DECLARE @COLUMNNAMES NVARCHAR(MAX)=''
DECLARE @SQL NVARCHAR(MAX)=''
;WITH  COL_NM
AS
(SELECT DISTINCT '['+COLUMN_NAME+'],'  AS CN FROM DBOOO.[SA0067].[UNPIVOT])
SELECT   @COLUMNNAMES +=CN FROM COL_NM
SET @COLUMNNAMES =LEFT(@COLUMNNAMES,LEN(@COLUMNNAMES)-1)
SET @SQL ='SELECT * FROM (
SELECT RECORD_ID,METRIC_NAME,NAME,COLUMN_Name,COLUMN_Value
 
 FROm DBOOO.[SA0067].[UNPIVOT]
 ) t
 PIVOT 
 ( MAX(COLUMN_Value)
 FOR COLUMN_Name IN ('+@COLUMNNAMES+')
 ) AS PT'
EXECUTE sp_executesql @SQL
7 Replies
- rodgerkongIron ContributorCan you write the script into a stored procedure, and then call the sp from Reporting Tool?
- VBA_ENTHU1988Copper Contributor
- SP - AS reporting team do not have access.
 - I tried fetching all values comma separated (STRING_AGG) exactly in same format as that of my column name variables but was unable to pass in dynamic select
 - kindly helpmif instead of declare PLSQL block same can be achieved by normal SQL sub queries/ cte/ etc.
 
- rodgerkongIron Contributor
Is this fits you?
CREATE TABLE #col (c nvarchar(10)) GO INSERT INTO #col VALUES('A'),('B'),('C'),('D'),('E') GO DECLARE @SQL NVARCHAR(MAX) WITH NM AS ( SELECT STRING_AGG(c, ',') AS N FROM #col ) SELECT @SQL = 'SELECT * FROM ( SELECT RECORD_ID,METRIC_NAME,NAME,COLUMN_Name,COLUMN_Value FROm DBOOO.[SA0067].[UNPIVOT] ) t PIVOT ( MAX(COLUMN_Value) FOR COLUMN_Name IN ('+ N + ') ) AS PT' FROM NM SELECT @SQL DROP TABLE #col