我有一个SQL数据库表,看起来像这样
Person | Color
Alex | red
Alex | blue
Alex | orange
Mike | green
Tom | blue
Tom | black
我需要制作这样的副本
Person | Color_1| Color_2| Color_3
Alex | red | blue | orange
Mike | green
Tom | blue | black
答案 0 :(得分:1)
我们需要动态地执行此操作。我们需要获得我们将要拥有的列总数。我们需要为PIVOT
创建一个动态T-SQL。
试试这个:
CREATE TABLE #DataSource
(
[name] VARCHAR(12)
,[color] VARCHAR(12)
);
INSERT INTO #DataSource ([name], [color])
VALUES ('Alex', 'red')
,('Alex', 'blue')
,('Alex', 'orange')
,('Mike', 'green')
,('Tom ', 'blue')
,('Tom ', 'black');
DECLARE @DynammicTSQLStatement NVARCHAR(MAX)
,@DynamicPIVOTColumns NVARCHAR(MAX);
DECLARE @MaxNumberOfColorsPerName INT;
WITH DataSource AS
(
SELECT COUNT([color]) OVER (PARTITION BY [name]) AS [ColorsCount]
FROM #DataSource
)
SELECT @MaxNumberOfColorsPerName = MAX([ColorsCount])
FROM DataSource;
SET @DynamicPIVOTColumns = STUFF
(
(
SELECT TOP (@MaxNumberOfColorsPerName) ',Color_' + CAST(ROW_NUMBER() OVER(ORDER BY t1.number) AS VARCHAR(12)) AS N
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
ORDER BY ROW_NUMBER() OVER (ORDER BY t1.number)
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET @DynammicTSQLStatement = N'
SELECT *
FROM
(
SELECT *
,''Color_'' + CAST(ROW_NUMBER() OVER (PARTITION BY [name] ORDER BY [color]) AS VARCHAR(12)) AS [color_number]
FROM #DataSource
) DS
PIVOT
(
MAX([color]) FOR [color_number] IN (' + @DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql @DynammicTSQLStatement;
DROP TABLE #DataSource;
答案 1 :(得分:0)
首先我将数据操作为所需的格式
IF OBJECT_ID('tempdb..##Getdata')IS NOT NULL
DROP TABLE ##Getdata
;With cte(Person, Color)
AS
(
SELECT 'Alex' , 'red' UNION ALL
SELECT 'Alex' , 'blue' UNION ALL
SELECT 'Alex' , 'orange' UNION ALL
SELECT 'Mike' , 'green' UNION ALL
SELECT 'Tom' , 'blue' UNION ALL
SELECT 'Tom' , 'black'
)
,Cte_Final
AS
(
SELECT DENSE_RANK()OVER(ORDER BY Person )AS Rnk
,Person
,Color
,'Color_'+CAST(DENSE_RANK()OVER(ORDER BY Person ) AS VARCHAR(2)) AS ColrCol
FROM cte
)
SELECT DISTINCT Rnk
,Person
,ColrCol
,STUFF((SELECT DISTINCT ', '+Color
FROM Cte_Final i WHERE i.Rnk=o.Rnk
FOR XML PATH ('')),1,1,'') AS
Color
INTO ##Getdata
FROM Cte_Final o
使用Dynamic Sql我得到了预期的结果
DECLARE @COlumn nvarchar(max),@Sql nvarchar(max)
SELECT @COlumn=STUFF((SELECT DISTINCT ', '+'Split.a.value(''/S['+CAST(Rnk AS VARCHAR(2))+']'''+','+'''nvarchar(100)'''+') As ' + QUOTENAME(ColrCol )
FROM ##Getdata i
FOR XML PATH ('')),1,1,'')
SET @Sql='SELECT DISTINCT Person,'+@COlumn+' FROM
(
SELECT Person,
CAST(''<S>''+REPLACE (Color,'','',''</S><S>'')+''</S>'' AS XML ) AS Color
FROM ##Getdata
) AS A
CROSS APPLY Color.nodes(''S'') AS Split(a)
'
PRINT @Sql
EXEC(@Sql)
结果
Person Color_1 Color_2 Color_3
--------------------------------
Alex blue orange red
Mike green NULL NULL
Tom black blue NULL
从以下链接查看演示 Expected Result for your data