sql server—编写sql查询以将表从a转换为b

aamkag61  于 2021-08-01  发布在  Java
关注(0)|答案(4)|浏览(352)

我有一个数据库表(表a)如下所示,在sql server 2016中:
表a:

ID     Group       2018     2019    2020
-----------------------------------------
ID1    Group A      200      300     400
ID2    Group B      100      800     ---
ID2    Group B      ----     500     300

我想编写一个sql查询或类似的东西,或者一个报表工具来生成一个报表/表(将表a转换为表b),如下所示:
表b:

ID       Group   -   Year  -      Value
----------------------------------------
ID1      Group A     2018         200
ID1      Group A     2019         300
ID1      Group A     2020         400
ID2      Group B     2018         100
ID2      Group B     2019         800
ID2      Group B     2019         500
ID2      Group B     2020         300

如果可以通过编写sql查询来实现,那就太好了。如果需要使用编程语言来编写程序或使用工具,也可以,但请让我知道使用什么和如何实现(我知道一些c#编程)。
(我知道我不应该使用id和group作为列名。我不会在数据库表中真正使用这个名称,只是为了简化这里的问题)
有人能帮忙吗?非常感谢你!

mbskvtky

mbskvtky1#

规范方法使用 union all :

select id, group, 2018 as year, "2018" from t
union all
select id, group, 2019 as year, "2019" from t
union all
select id, group, 2020 as year, "2018" from t;

但是,在sql server中,我强烈建议 apply :

select t.id, t.group, v.*
from t cross apply
     (values (2018, [2018]), (2019, [2019]), (2020, [2020])
     ) v(year, value)
where v.value is not null;
qqrboqgw

qqrboqgw2#

以防随着时间的推移出现变量或附加列。
请注意,您只需排除某些列,并省略空值。
充分披露:戈登的申请是一个更有效的推动。
例子

Select A.[ID]
      ,A.[Group]
      ,[Year] = B.[Key]
      ,[Value] = try_convert(int,B.[Value])  --<< choose the proper data type (optional)
 From  YourTable A
 Cross Apply (
                Select *
                 From OpenJson( (Select A.* For JSON Path,Without_Array_Wrapper ) ) 
                 Where [Key] not in ('ID','Group')
             ) B

退货

ID  Group       Year    Value
ID1 Group A     2018    200
ID1 Group A     2019    300
ID1 Group A     2020    400
ID2 Group B     2018    100
ID2 Group B     2019    800
ID2 Group B     2019    500
ID2 Group B     2020    300

编辑—如果不是2016,则为xml版本+

Select A.[ID]
      ,A.[Group]
      ,[Year]  = replace(replace(C.[Item],'X003',''),'_','')
      ,[Value] = try_convert(int,C.[Value])  --<< choose the proper data type (optional)
 From  YourTable A
 Cross Apply ( values ( convert(xml,(Select A.* for XML RAW)) ) ) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(max)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)', 'varchar(100)') not in ('ID','Group')
             ) C
kx7yvsdv

kx7yvsdv3#

使用unpivot的解决方案:

select * from A
UNPIVOT 
(
   [value] for [Year] in ([2018],[2019],[2020])
)u;

希望有帮助。!

o2rvlv0m

o2rvlv0m4#

这是我的解决方案,完全符合你的需要
我将关键字和年份用方括号括起来作为列名

Select id, [Group], [year], value
from
(
select id, [Group], 2018 as [year], [2018] as value from a
union all
select id, [Group], 2019 as [year], [2019] as value from a
union all
select id, [Group], 2020 as [year], [2020] as value from a
) Q
Where value is not null
order by id, [Group], [year]

这是小提琴

相关问题