动态 SQL 使用多列交叉应用反透视数据

Dynamic SQL to Unpivot Data using Cross Apply with Multiple Columns

Microsoft SQL Server Management Studio v18.8

我有一个 table,它将具有不同的列和列名称。我需要对数据进行逆透视,以便最终将其存储到不同的 table。不幸的是,这是从 Google Sheet.

中提取原始 table 的过程

我在这里查了几篇文章和答案,但我无法成功复制其中任何一篇。我需要根据项目、时间戳和位置进行逆透视。那么 Q1、Q2、Q3 等应该是未透视的。下面是一个示例 table 和将获得我想要的结果的查询。非常感谢在动态 SQL 中为未来的专栏 additions/modifications 提供任何帮助。我愿意使用 UNPIVOT 或任何其他功能来获得所需的结果。实际数据源将是永久的 table,而不是临时的 table。

创建Table

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','No','Yes','Yes'),
                        ('Pen','2021-04-06 15:00:00.000','MX','Yes','Yes','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

结果

编辑 - XML 版本更新

Select A.Item
      ,A.Timestamp
      ,A.Location
      ,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','Timestamp','Location')
             ) C