使用多列交叉应用对数据进行逆透视的动态 SQL

问题描述

Microsoft sql Server Management Studio v18.8

我有一个包含不同列和列名的表。我需要对数据进行逆透视,以便最终可以将其存储到不同的表中。不幸的是,这是因为原始表格是从 Google 表格中提取出来的。

在这里查找了几篇文章和答案,但我无法成功复制其中任何一篇。我需要根据项目、时间戳和位置进行逆透视。那么 Q1、Q2、Q3 等应该是非旋转的。下面是一个示例表和查询,它将获得我想要的结果。在动态 sql获取此信息以供将来添加/修改列的任何帮助将不胜感激。我愿意使用 UNPIVOT 或任何其他功能来获得所需的结果。实际数据源将是一个永久表,而不是临时表。

创建表格

DROP TABLE IF EXISTS #test
CREATE TABLE #test (Item VARCHAR(16),Timestamp DATETIME,Location VARCHAR(2),Q1 VARCHAR(3),Q2 VARCHAR(3),Q3 VARCHAR(3))
INSERT INTO #test VALUES('Stapler','2021-04-14 12:00:00.000','US','Yes','No','Yes'),('Paper','2021-04-10 16:00:00.000','CA',('Pen','2021-04-06 15:00:00.000','MX','No')

使用交叉应用取消旋转

 SELECT A.Item,A.Timestamp,A.Location,B.*
      FROM #test AS A
    CROSS APPLY
    (
     VALUES ('Q1',A.Q1),('Q2',A.Q2),('Q3',A.Q3)
    ) B (Question,Answer)

解决方法

您可以使用一些 JSON 来动态取消数据透视。如果不是 2016+ ... 有类似的 XML 方法。

示例

Select A.Item,A.Timestamp,A.Location,B.*
 From  #test A
 Cross Apply (
                Select Question = [Key],Answer   = [Value]
                 From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper,INCLUDE_NULL_VALUES  ) ) 
                 Where [Key] not in ('Item','Timestamp','Location')
             ) B

结果

enter image description here

编辑 - XML 版本更新

Select A.Item,C.*
 From  #test A
 Cross Apply ( values ((Select A.* for XML RAW,Type)) )B(XMLData)
 Cross Apply (
                Select Question = xAttr.value('local-name(.)','varchar(100)'),Answer   = xAttr.value('.','varchar(max)')
                 From XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)','varchar(100)')  not in ('Item','Location')
             ) C

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...