组合数据的半转置

问题描述 投票:2回答:2

请考虑以下查询:

DECLARE @T1 TABLE(
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Data] VARCHAR(100),
  [Column1] VARCHAR(100),
  [Column2] VARCHAR(100),
  [Column3] VARCHAR(100));

INSERT INTO @T1([Data],[Column1],[Column2],[Column3])
    VALUES
        ('Data1','C11','C21','C31'),
        ('Data2','C12','C22','C32'),
        ('Data3','C13','C23','C33'),
        ('Data4','C14','C24','C34'),
        ('Data5','C15','C25','C35');

SELECT * FROM @T1;

输出如下所示:

enter image description here

现在我们要保持Data列和每个其他列堆栈将该列的select结果保存到final表中。换句话说,以下查询生成输出:

-- I am looking for a better solution than below!
DECLARE @output TABLE([Data] VARCHAR(100),[Column] VARCHAR(100));

INSERT INTO @output([Data],[Column])
    (SELECT [Data],[Column1] FROM @T1
      UNION
    SELECT [Data],[Column2] FROM @T1
      UNION
    SELECT [Data],[Column3] FROM @T1)

SELECT * FROM @output

什么是比上面更好的清洁方法来产生最终输出?随着色谱柱数量的增加,它意味着每个新色谱柱都需要一个单独的插入物,这似乎是一个粗糙的解决方案。理想情况下,我正在寻找基于枢轴的解决方案,但我无法想出具体的东西。

enter image description here

sql sql-server tsql sql-server-2016 sql-server-2017
2个回答
1
投票

我经常使用apply而不是union

select t1.data, t2.cols
from @t1 t1 cross apply
     ( values ([column1]), ([column2]), ([column3]) ) t2(cols);

2
投票

当然Yogesh的解决方案会更高效。但是,由于您的列会随着时间的推移而扩展,因此这里有一种方法可以“动态”取消您的数据,而无需实际使用Dynamic SQ:

Select A.[Data]
      ,C.*
 From  @T1 A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(100)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)','varchar(100)') not in ('Id','Data','Other-Columns','To-Exclude')
             ) C

返回

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.