MS SQL 多列数据

MS SQL Pivot dat from long with multiple columns

我想将具有多个 id 列的 table 从长转为宽。 我为一列找到了解决方案,但没有为多列找到解决方案。 我可以为一个专栏改编的最接近的解决方案是这个

我的 table 大致是这样的,

create table t (id int, date date, varA_id int, VarB_id int, value int)
insert into t values
 (1,'2005-01-20',1, 1,197)
,(2,'2005-01-20',1,2,58)
,(3,'2005-01-20',1,3,90)
,(4,'2005-01-20',2,1,210)
,(5,'2005-01-20',2,2,133)
,(6,'2005-01-20',2,3,67)
,(7,'2005-01-20',3,1,87)
,(8,'2005-01-20',3,2,87)
,(9,'2005-01-20',3,3,87)

实际上没有日期,但没关系。我想以一种方式传播,以便为 VarA_idVarB_id

的每个排列获取列

所以我的预期结果是这样的

我的实际 table 有三个 _id 列和更多排列,所以我真的需要一个通用的解决方案。

基于我 link 中的其他解决方案,我希望这样的方法能奏效。我调整了创建列名的顶部,这会起作用。我不知道如何真正调整获取值的底部。

declare @cols nvarchar(max);
declare @sql  nvarchar(max);
  select @cols = stuff((
    select distinct 
      ', ' + 'VarA_'+convert(varchar(10),varA_id) + '_VarB_'+convert(varchar(10),varB_id)
      from t 
      order by 1
      for xml path (''), type).value('.','nvarchar(max)')
    ,1,2,'')
select  @sql = '
 select Id, date, ' + @cols + '
  from  (
    select Id, date, varA_id = ''v''+convert(varchar(10),varA_id), value
      from t
      ) as t
 pivot (sum([value]) for [varA_id] in (' + @cols + ') ) p'
select @sql
exec(@sql);

好的,到目前为止,我自己的解决方案是添加一个帮助栏,基本上只是做其他问题所做的事情。我需要对此进行改进,所以我没有添加专栏,我想要更好的名称,但至少这显示了我想要的。

alter table t add help_col nvarchar(10)
Update t
set help_col=convert(varchar(10),varA_id)+convert(varchar(10),varB_id)

declare @cols nvarchar(max);
declare @sql  nvarchar(max);
  select @cols = stuff((
    select distinct 
      ', ' + 'v'+convert(varchar(10),help_col)
      from t 
      order by 1
      for xml path (''), type).value('.','nvarchar(max)')
    ,1,2,'')
select  @sql = '
 select date, ' + @cols + '
  from  (
    select date, help_col = ''v''+convert(varchar(10),help_col), value
      from t
      ) as t
 pivot (sum([value]) for [help_col] in (' + @cols + ') ) p'
select @sql
exec(@sql);

结果是

   select date, v11, v12, v13, v21, v22, v23, v31, v32, v33    from  (      select date, help_col = 'v'+convert(varchar(10),help_col), value        from t        ) as t   pivot (sum([value]) for [help_col] in (v11, v12, v13, v21, v22, v23, v31, v32, v33) ) p

产生

date        v11 v12 v13 v21 v22 v23 v31 v32 v33
2005-01-20  197 58  90  210 133 67  87  87  87

你动态的主要问题sql?
是源查询中构造的名称与生成的列名称不匹配。

这是一个修复方法:

declare @cols varchar(max) = null;
declare @sql  nvarchar(max);

select @cols = concat(@cols+', '+char(10), quotename(concat('VarA_', varA_id, '_VarB_', varB_id))) 
from test
group by varA_id, varB_id
order by varA_id, varB_id;

-- select @cols as cols;

set @sql = 'select * '+char(10)+
  'from ( ' +char(10)+
  ' select [date], [value], ' +char(10)+
  ' concat(''VarA_'',varA_id,''_VarB_'',varB_id) as Col ' +char(10)+
  ' from test ' +char(10)+
  ') as src ' +char(10)+
  'pivot (sum([value]) for Col in ('+char(10)+ @cols +char(10)+')) pvt';
 
-- select @sql as sql;

exec(@sql);
date VarA_1_VarB_1 VarA_1_VarB_2 VarA_1_VarB_3 VarA_2_VarB_1 VarA_2_VarB_2 VarA_2_VarB_3 VarA_3_VarB_1 VarA_3_VarB_2 VarA_3_VarB_3
2005-01-20 197 58 90 210 133 67 87 87 87

db<>fiddle here