SQL 将一行转换为具有未知数量的不同值的列

SQL transforming one row to columns with unknown number of distinct values

我有以下数据库

id  item_id  date        system_code  value
#1  0001     01-01-2019  0999         10
#2  0001     02-01-2019  0888         15
#3  0001     01-01-2019  0999         10
#4  0002     02-01-2019  0777         20
#5  0002     03-01-2019  0777         35

我想要实现的结果看起来像这样,system_code 列的值是“值”

的总和
  item_id  date        0999  0888  0777
  0001     01-01-2019  20        
  0001     02-01-2019        15
  0002     02-01-2019              20
  0002     03-01-2019              35

我的问题是 system_code 有超过 1000 个不同的值,所以我无法手动输入它们。 数据库有近十亿个条目,所以任何能快速计算的东西都是完美的。

您可以使用条件聚合:

select item_id, date,
       max(case when system_code = '0999' then value end) as value_0999,
       max(case when system_code = '0888' then value end) as value_0888,
       max(case when system_code = '0777' then value end) as value_0777
from t
group by item_id, date;

您可以使用查询生成此 max() 表达式:

select distinct
       replace('max(case when system_code = '<val>' then value end) as value_<val>,',
               '<val>', system_code
              )
from t;

以防万一,这里有一个动态 PIVOT

例子

Declare @SQL varchar(max) = stuff((Select distinct  ',' + QUOTENAME([system_code]) 
                                     From YourTable
                                     Order By 1 Desc
                                    For XML Path('') )
                                   ,1,1,'') 

Set @SQL = '
Select *
 From  ( Select item_id,date,system_code,value from YourTable ) src
 Pivot ( sum(value) for system_Code in ( '+ @SQL + ') ) pvt
'

--Print @SQL
Exec(@SQL)

Returns

注:

我相信最大列数是 1,024(宽 table 30,000)。

就个人而言,我不希望消耗超过 50 列。

编辑:

如果您有两列,您可以通过在第一个查询中添加 WHERE 来过滤列表,也许 运行 两次(或更多)。结果将具有相同的行数,只是不同的列集。

例子

Declare @SQL varchar(max) = stuff((Select distinct  ',' + QUOTENAME([system_code]) 
                                   From #YourTable
                                   Where [system_code] >'0500' -- or any appropriate filter
                                   Order By 1 desc
                                   For XML Path('') )
                                  ,1,1,'')