2016-03-04 111 views
0

此问题源于此one。下面的SQL做工精细:添加动态旋转数据的动态占位符列

IF OBJECT_ID('tempdb..#Source') IS NOT NULL DROP TABLE #Source 
IF OBJECT_ID('tempdb..#Aim') IS NOT NULL DROP TABLE #Aim 

CREATE TABLE #Source 
(
    ColumnName NVARCHAR(10), 
    ColumnValue NVARCHAR(10), 
    Id INT 
) 

CREATE TABLE #Aim 
(
    Id INT, 
    Column1 NVARCHAR(10), 
    Column2 NVARCHAR(10), 
    Column3 NVARCHAR(10) 
) 

INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column1', 'Value1', 1); 
INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column2', 'Value1', 1); 
INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column1', 'Value2', 2); 
INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column1', 'Value4', 3); 
INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column3', 'Value1', 3); 
INSERT INTO #Source (ColumnName, ColumnValue, Id) VALUES ('Column3', 'Value3', 4); 

INSERT INTO #Aim (Id, Column1, Column2, Column3) VALUES (1, 'Value1', 'Value1', NULL) 
INSERT INTO #Aim (Id, Column1, Column2, Column3) VALUES (2, 'Value2', NULL, NULL) 
INSERT INTO #Aim (Id, Column1, Column2, Column3) VALUES (3, 'Value4', NULL, 'Value1') 
INSERT INTO #Aim (Id, Column1, Column2, Column3) VALUES (4, NULL, NULL, 'Value3') 

DECLARE @col_list VARCHAR(max) = (SELECT Quotename(ColumnName) + ',' 
    FROM #Source 
    GROUP BY ColumnName 
    ORDER BY ColumnName 
    FOR xml path('')) -- To create the dynamic column list 

SET @col_list = LEFT(@col_list, Len(@col_list) - 1) -- To remove the leading comma 

DECLARE @sql NVARCHAR(max) 

SELECT @sql = 'select * from #Source 
pivot (max(ColumnValue) for ColumnName in (' 
       + @col_list + '))pv' 

EXEC Sp_executesql @sql -- Execute the dynamic sql 

所面临的挑战是,我想,如果有小于n列添加虚拟列。因此,对于n = 5,我想实现这个作为输出:

Id Column1 Column2 Column3 Dummy4 Dummy5 
1 Value1 Value1 NULL NULL NULL 
2 Value2 NULL NULL NULL NULL 
3 Value4 NULL Value1 NULL NULL 
4 NULL NULL Value3 NULL NULL 

这可能非常有n为变量?

回答

1

这里有一种方法

DECLARE @n INT = 5 
DECLARE @cnt INT = (SELECT Count(DISTINCT ColumnName) 
    FROM #Source) 
DECLARE @col_list VARCHAR(max) = (SELECT Quotename(ColumnName) + ',' 
    FROM #Source 
    GROUP BY ColumnName 
    ORDER BY ColumnName 
    FOR xml path('')) -- To create the dynamic column list 
SET @col_list = LEFT(@col_list, Len(@col_list) - 1) 

WHILE @cnt + 1 <= @n -- To create the dummy list based on existing count 
    BEGIN 
     SET @col_list+=',[dummy' + Cast(@cnt + 1 AS VARCHAR(100)) + ']' 
     SET @cnt = @cnt + 1 
    END 

DECLARE @sql NVARCHAR(max) 

SELECT @sql = 'select * from #Source 
    pivot (max(ColumnValue) for ColumnName in (' 
       + @col_list + '))pv' 

--PRINT @sql 

EXEC Sp_executesql @sql 

结果:

╔════╦═════════╦═════════╦═════════╦════════╦════════╗ 
║ Id ║ Column1 ║ Column2 ║ Column3 ║ dummy4 ║ dummy5 ║ 
╠════╬═════════╬═════════╬═════════╬════════╬════════╣ 
║ 1 ║ Value1 ║ Value1 ║ NULL ║ NULL ║ NULL ║ 
║ 2 ║ Value2 ║ NULL ║ NULL ║ NULL ║ NULL ║ 
║ 3 ║ Value4 ║ NULL ║ Value1 ║ NULL ║ NULL ║ 
║ 4 ║ NULL ║ NULL ║ Value3 ║ NULL ║ NULL ║ 
╚════╩═════════╩═════════╩═════════╩════════╩════════╝