sql将列转换为行

jtjikinw  于 2021-08-01  发布在  Java
关注(0)|答案(2)|浏览(237)

我要执行以下转换:

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

如果可能的话,我希望在转换表中也保留字段名,即rowid=0的所有行都将添加前辈作为字段,rowid=1将包含price,依此类推。

ercv8c1e

ercv8c1e1#

这里有一个使用json的选项,如果2016+xml版本可用于旧版本。
例子

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

退货

编辑-只是为了好玩,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

edit—允许空值的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

退货

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
dddzy1tm

dddzy1tm2#

一般来说, 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;

相关问题