透视行 反透视多列

时间:2021-05-07 01:54:07

标签: sql sql-server tsql

我有一个多连接查询来获得以下结果。

Color   Size    AQty       BQty        CQty        DQty
A1      L       1           2           3           4
A1      M       1           2           3           4
A1      S       1           2           3           4
A1      XL      1           2           3           4
B1      L       1           2           3           4
B1      M       1           2           3           4
B1      S       1           2           3           4
B1      XL      1           2           3           4
B1      XXL     1           2           3           4
C1      S       1           2           3           4
C1      L       1           2           3           4

但是现在如何区分大小字段行到列,然后 AQty、BQty、CQty 和 DQty 列到行?我想要以下结果。

Color   Total   L  M    S   XL  XXL
A1      AQty    1  1    1   1   0
A1      BQty    2  2    2   2   0
A1      CQty    3  3    3   3   0
A1      DQty    4  4    4   4   0
B1      AQty    1  1    1   1   1
B1      BQty    2  2    2   2   2
B1      CQty    3  3    3   3   3
B1      DQty    4  4    4   4   4
C1      AQty    1  0    1   0   0
C1      BQty    2  0    2   0   0
C1      CQty    3  0    3   0   0
C1      DQty    4  0    4   0   0

我想要这样的问题结果enter link description here,但我的大小字段是动态数据。如何区分大小字段动态数据?我不知道如何编码,我尝试了以下代码但没有成功。

DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX);
SET @cols = STUFF(
                 (
                     SELECT DISTINCT 
                            ','+ Size
                     FROM testpovit c FOR XML PATH(''), TYPE
                 ).value('.', 'nvarchar(max)'), 1, 1, '');

SET @query = 'select size = col,color,total,
         '+@cols+'
        from
        (
          select color,total col, value
          from testpovit
          cross apply
          (
            select AQty, cast(AQty as varchar(10)) union all
            select BQty, cast(BQty as varchar(10)) union all
            select CQty, cast(BQty as varchar(10)) union all
            select DQty, cast(BQty as varchar(10)) 
          ) c(col, value)
        ) d
        pivot
        (
          max(value)
          for size in ( '+@cols+')
        ) piv';
print @query
EXECUTE (@query);

这是SQL脚本

CREATE TABLE test([color] varchar(5), [size] varchar(5),[AQty] varchar(10),[BQty] varchar(10),[CQty] varchar(10),[DQty] varchar(10));

INSERT INTO test
    ([color], [size], [AQty], [BQty],[CQty],[DQty])
VALUES
    ('A1', 'L','1','2','3','4'),
    ('A1', 'M','1','2','3','4'),
    ('A1', 'S','1','2','3','4'),
    ('A1', 'XL','1','2','3','4'),
    ('B1', 'L','1','2','3','4'),
    ('B1', 'M','1','2','3','4'),
    ('B1', 'S','1','2','3','4'),
    ('B1', 'XL','1','2','3','4'),
    ('B1', 'XXL','1','2','3','4'),
    ('C1', 'L','1','2','3','4'),
    ('C1', 'S','1','2','3','4');

1 个答案:

答案 0 :(得分:0)

你可以这样做:

CREATE TABLE #temp([color] varchar(5), [size] varchar(5),[AQty] varchar(10),[BQty] varchar(10),[CQty] varchar(10),[DQty] varchar(10));

INSERT INTO #temp([color], [size], [AQty], [BQty],[CQty],[DQty])
VALUES   ('A1', 'L','1','2','3','4')
       , ('A1', 'M','1','2','3','4')
       , ('A1', 'S','1','2','3','4')
       , ('A1', 'XL','1','2','3','4')
       , ('B1', 'L','1','2','3','4')
       , ('B1', 'M','1','2','3','4')
       , ('B1', 'S','1','2','3','4')
       , ('B1', 'XL','1','2','3','4')
       , ('B1', 'XXL','1','2','3','4')
       , ('C1', 'L','1','2','3','4')
       , ('C1', 'S','1','2','3','4')

declare @cols as varchar(max), @sql varchar(max)
select @cols = STRING_AGG(col, ', ') from (
    select distinct QUOTENAME(size) as col from #temp
) as t

set @sql = '
select color, col as total, ' + @cols + '
from(
    select color, size, col, [value]
    from #temp
    cross apply (
    select ''AQty'', cast(AQty as varchar(10)) union all
    select ''BQty'', cast(BQty as varchar(10)) union all
    select ''CQty'', cast(CQty as varchar(10)) union all
    select ''DQty'', cast(DQty as varchar(10)) 
    ) c(col, [value])
) d
pivot
(
  max(value)
  for size in (' + @cols + ')
) piv
order by color, total
'
exec(@sql)