考虑以下查询:
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;
输出如下所示:
现在,我们要保留“数据”列,并将其他各列的选择结果堆叠到最终表中。换句话说,以下查询将产生输出:
-- 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
有什么比上面的方法更干净的方法来产生最终输出的呢?随着列数的增加,这意味着对于每个新列,我都需要有一个单独的插件,这似乎是一个粗略的解决方案。理想情况下,我正在寻找基于枢轴的解决方案,但我无法提出具体的建议。
答案 0 :(得分:2)
当然,Yogesh的解决方案会更高效。但是,由于您的列会随着时间的推移而扩展,因此,以下一种方法将使用动态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
返回
答案 1 :(得分:1)
我经常使用apply
而不是union
:
select t1.data, t2.cols
from @t1 t1 cross apply
( values ([column1]), ([column2]), ([column3]) ) t2(cols);