SQL 将列转换为行
SQL Converting Columns to Rows
我要执行以下转换:
Seniority Price Rating
---------------------------
1 P1 R1
2 P2 R2
3 P3 R3
至
Value RowId ColId
------------------
1 0 0
P1 0 1
R1 0 2
2 1 0
P2 1 1
R2 1 2
3 2 0
P3 2 1
R3 2 2
如果可能,我想在转换后的 table 中也保留字段名称,即所有 rowid=0 的行都将添加 Seniority 作为字段,rowid=1 将添加 Price,依此类推.
作为一般方法,union all
有效:
select seniority, 'seniority' as which, seniority - 1, 0
from t
union all
select p1, 'p1' as which, seniority - 1, 1
from t
union all
select r1, 'r1' as which, seniority - 1, 2
from t;
如果 2016+ 有一个 XML 版本可用于旧版本,这里是一个使用 JSON 的选项。
例子
Declare @YourTable Table ([Seniority] varchar(50),[Price] varchar(50),[Rating] varchar(50))
Insert Into @YourTable Values
(1,'P1','R1')
,(2,'P2','R2')
,(3,'P3','R3')
Select B.Value
,A.RowID
,B.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable --<<< Replace with virtually any table.
) A
Cross Apply (
Select *
,ColID = row_number() over (order by (select null)) - 1
From OpenJson( (Select A.* For JSON Path,Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
Where [Key] not in ('RowID')
) B
Returns
编辑 - 仅供娱乐,XML 版本
Select C.Value
,A.RowID
,C.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable
) A
Cross Apply ( values ( convert(xml,(Select A.* for XML RAW)) ) ) B(XMLData)
Cross Apply (
Select ColID = row_number() over( order by (select null)) - 1
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('RowID')
) C
编辑——XML允许空值的版本
Declare @YourTable Table ([Seniority] varchar(50),[Price] varchar(50),[Rating] varchar(50))
Insert Into @YourTable Values
(1,'P1','R1')
,(2,'P2','R2')
,(3,NULL,'R3') -- Forced a NULL value
Select C.Value
,A.RowID
,C.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable
) A
Cross Apply ( values ( convert(xml,(Select A.* for XML RAW,ELEMENTS XSINIL)) ) ) B(XMLData)
Cross Apply (
Select Item = attr.value('local-name(.)','varchar(100)')
,Value = attr.value('.','varchar(max)')
,ColID = row_number() over (order by (select null)) - 1
From XMLData.nodes('/row') as C1(nd)
Cross Apply C1.nd.nodes('./*') as C2(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('RowID')
) C
Returns
Value RowID ColID
1 0 0
P1 0 1
R1 0 2
0 0 3
2 1 0
P2 1 1
R2 1 2
1 1 3
3 2 0
2 1 --<< Notice NULLs return as Empty Strings
R3 2 2
2 2 3
我要执行以下转换:
Seniority Price Rating
---------------------------
1 P1 R1
2 P2 R2
3 P3 R3
至
Value RowId ColId
------------------
1 0 0
P1 0 1
R1 0 2
2 1 0
P2 1 1
R2 1 2
3 2 0
P3 2 1
R3 2 2
如果可能,我想在转换后的 table 中也保留字段名称,即所有 rowid=0 的行都将添加 Seniority 作为字段,rowid=1 将添加 Price,依此类推.
作为一般方法,union all
有效:
select seniority, 'seniority' as which, seniority - 1, 0
from t
union all
select p1, 'p1' as which, seniority - 1, 1
from t
union all
select r1, 'r1' as which, seniority - 1, 2
from t;
如果 2016+ 有一个 XML 版本可用于旧版本,这里是一个使用 JSON 的选项。
例子
Declare @YourTable Table ([Seniority] varchar(50),[Price] varchar(50),[Rating] varchar(50))
Insert Into @YourTable Values
(1,'P1','R1')
,(2,'P2','R2')
,(3,'P3','R3')
Select B.Value
,A.RowID
,B.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable --<<< Replace with virtually any table.
) A
Cross Apply (
Select *
,ColID = row_number() over (order by (select null)) - 1
From OpenJson( (Select A.* For JSON Path,Without_Array_Wrapper,INCLUDE_NULL_VALUES ) )
Where [Key] not in ('RowID')
) B
Returns
编辑 - 仅供娱乐,XML 版本
Select C.Value
,A.RowID
,C.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable
) A
Cross Apply ( values ( convert(xml,(Select A.* for XML RAW)) ) ) B(XMLData)
Cross Apply (
Select ColID = row_number() over( order by (select null)) - 1
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('RowID')
) C
编辑——XML允许空值的版本
Declare @YourTable Table ([Seniority] varchar(50),[Price] varchar(50),[Rating] varchar(50))
Insert Into @YourTable Values
(1,'P1','R1')
,(2,'P2','R2')
,(3,NULL,'R3') -- Forced a NULL value
Select C.Value
,A.RowID
,C.ColID
From (Select *
,RowID = row_number() over (order by (select null)) - 1
From @YourTable
) A
Cross Apply ( values ( convert(xml,(Select A.* for XML RAW,ELEMENTS XSINIL)) ) ) B(XMLData)
Cross Apply (
Select Item = attr.value('local-name(.)','varchar(100)')
,Value = attr.value('.','varchar(max)')
,ColID = row_number() over (order by (select null)) - 1
From XMLData.nodes('/row') as C1(nd)
Cross Apply C1.nd.nodes('./*') as C2(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('RowID')
) C
Returns
Value RowID ColID
1 0 0
P1 0 1
R1 0 2
0 0 3
2 1 0
P2 1 1
R2 1 2
1 1 3
3 2 0
2 1 --<< Notice NULLs return as Empty Strings
R3 2 2
2 2 3