今天,我的同事要求我将数据从垂直登台表转换为水平表。我的意思是将行转换为列。我使用了PIVOT并解决了它。但是遇到了这样的情况:如果数据字段重复自身,则在移动数据时会遇到麻烦。
这是我正在处理的测试数据:
CREATE TABLE STAGING ( ENTITYID INT, PROPERTYNAME VARCHAR(25), PROPERTYVALUE VARCHAR(25) ) INSERT INTO STAGING VALUES (1, 'NAME', 'DONNA') INSERT INTO STAGING VALUES (1, 'SPOUSE', 'HENRY') INSERT INTO STAGING VALUES (1, 'CHILD', 'JACK') INSERT INTO STAGING VALUES (2, 'CHILD', 'KAYALA')
我使用PIVOT将行数据显示为列:
SELECT * FROM (SELECT ENTITYID, PROPERTYNAME, PROPERTYVALUE FROM STAGING) AS T PIVOT (MAX(PROPERTYVALUE) FOR PROPERTYNAME IN (NAME, SPOUSE, CHILD)) AS T2
输出为:
ENTITYID NAME SPOUSE CHILD 1 DONNA HENRY JACK 2 NULL NULL KAYALA
但他希望输出如下:
ENTITYID NAME SPOUSE CHILD CHILD 1 DONNA HENRY JACK KAYALA
最重要的是,登台表中可以有多个CHILD属性。我们需要考虑这一点,并将所有儿童移动到列中。
这可能吗?
您可以在属性名称中添加一个行号,该行号将允许您执行所需的操作:
SELECT * FROM ( SELECT ENTITYID , PROPERTYNAME = PROPERTYNAME + CAST(ROW_NUMBER() OVER(PARTITION BY ENTITYID, PROPERTYNAME ORDER BY PROPERTYVALUE) AS VARCHAR(5)) ,PROPERTYVALUE FROM #STAGING ) AS T PIVOT (MAX(PROPERTYVALUE) FOR PROPERTYNAME IN (NAME1, SPOUSE1, CHILD1, CHILD2, CHILD3, CHILD4, CHILD5)) AS T2
我在这里假设ENTITYID将孩子与父母联系起来,即同一个人的所有孩子的ENTITYID为1,但是您的示例为Kayala显示了2。
这是一个演示:SQL Fiddle
如果您只想要CHILD字段的数字,则可以输入以下内容:
PROPERTYNAME = CASE WHEN PROPERTYNAME LIKE '%CHILD%' THEN PROPERTYNAME + CAST(ROW_NUMBER() OVER(PARTITION BY ENTITYID, PROPERTYNAME ORDER BY PROPERTYVALUE) AS VARCHAR(5)) ELSE PROPERTYNAME END
然后从IN()语句中的其他字段中删除该数字。
奖励问题-动态地执行上述操作: 我们不想假设人们只有一个配偶或2.3个孩子,因此我们会动态地进行全部操作:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) SELECT @cols = STUFF((SELECT ',' + PROPERTYNAME FROM (SELECT DISTINCT PROPERTYNAME = PROPERTYNAME + CAST(ROW_NUMBER() OVER(PARTITION BY ENTITYID, PROPERTYNAME ORDER BY PROPERTYVALUE) AS VARCHAR(5)) FROM STAGING )sub ORDER BY CASE WHEN PROPERTYNAME LIKE '%NAME%' THEN 1 WHEN PROPERTYNAME LIKE '%SPOUSE%' THEN 2 WHEN PROPERTYNAME LIKE '%CHILD%' THEN 3 ELSE 4 END ,RIGHT(PROPERTYNAME,1) FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') SET @query = 'SELECT * FROM ( SELECT ENTITYID, PROPERTYNAME = PROPERTYNAME + CAST(ROW_NUMBER() OVER(PARTITION BY ENTITYID, PROPERTYNAME ORDER BY PROPERTYVALUE) AS VARCHAR(5)),PROPERTYVALUE FROM STAGING ) AS T PIVOT (MAX(PROPERTYVALUE) FOR PROPERTYNAME IN ('+@cols+')) AS T2 ' EXEC(@query)
注意:此顺序仅适用于1-9岁的配偶和1-9岁的孩子,您可以对其进行调整以适合自己,但无论如何都是任意的。