0

我有一个包含以下数据的 SQL Server 表

SKU || Value || Volume 
 AB      2        3
 AB      2        2
 BB      1        3  

预期输出:

AB(value) || BB (VALUE) || AB(Volume) || BB (Volume)     
   4             1              5           3

注意:Sku列数据将是动态的

谢谢

4

2 回答 2

3

您可以使用 PIVOT 函数来获取结果。由于您将拥有未知数量的SKU值,因此我将首先编写查询的硬编码版本,然后将其转换为动态 SQL。

由于您有两列要从中透视数据valuevolume,那么我首先将这两列取消透视为多行,然后应用 PIVOT 函数。unpivot 语法可以使用 UNPIVOT 函数或 CROSS APPLY:

select col = t.sku+'_'+ c.col, 
  c.val
from yourtable t
cross apply
(
  select 'value', value union all
  select 'volume', volume
) c (col, val)

请参阅演示。这给出了一个结果:

|       COL | VAL |
|  AB_value |   2 |
| AB_volume |   3 |
|  AB_value |   2 |
| AB_volume |   2 |
|  BB_value |   1 |
| BB_volume |   3 |

将数据转换为与此类似的格式后,您可以应用 PIVOT:

select AB_Value, BB_Value, AB_Volume, BB_Volume
from
(
  select col = t.sku+'_'+ c.col, 
    c.val
  from yourtable t
  cross apply
  (
    select 'value', value union all
    select 'volume', volume
  ) c (col, val)
) d
pivot
(
  sum(val)
  for col in (AB_Value, BB_Value, AB_Volume, BB_Volume)
) piv;

请参阅SQL Fiddle with Demo。现在,由于您将拥有未知数量的值,因此您将不得不使用动态 SQL 来生成您需要执行的 SQL 字符串:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(sku+'_'+col) 
                    from yourtable
                    cross apply
                    (
                      select 'value', 1 union all
                      select 'volume', 2
                    ) c (col, so)
                    group by sku, so, col
                    order by so, sku
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT ' + @cols + ' 
            from 
            (
              select col = t.sku+''_''+ c.col, 
                c.val
              from yourtable t
              cross apply
              (
                select ''value'', value union all
                select ''volume'', volume
              ) c (col, val)
            ) x
            pivot 
            (
                sum(val)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

请参阅SQL Fiddle with Demo。两个版本都给出了结果:

| AB_VALUE | BB_VALUE | AB_VOLUME | BB_VOLUME |
|        4 |        1 |         5 |         3 |
于 2013-09-25T13:01:14.563 回答
0

SQL小提琴

MS SQL Server 2008 架构设置

CREATE TABLE Table1
    ([SKU] varchar(2), [Value] int, [Volume] int)
;

INSERT INTO Table1
    ([SKU], [Value], [Volume])
VALUES
    ('AB', 2, 3),
    ('AB', 2, 2),
    ('BB', 1, 3)
;

查询 1

DECLARE @colTable table(rownum int,columnName varchar(20),value int,volume int)
INSERT INTO @colTable SELECT row_number() over (ORDER BY SKU), SKU, 
                             SUM(Value), SUM(Volume) FROM Table1 GROUP BY SKU
DECLARE @query varchar(500)
DECLARE @i int, @max int
SET @i = 1
SET @max = (SELECT count(*) FROM @colTable)
SET @query = 'select '
WHILE @i <= @max
BEGIN
    IF @i > 1 SET @query = @query + ','
    SET @query = @query + 
             (SELECT cast(value as varchar) FROM @colTable WHERE rownum = @i) + 
             ' AS "' + 
             (SELECT columnName FROM @colTable WHERE rownum = @i) + '(Value)"'
    SET @query = @query + ','
    SET @query = @query + 
             (SELECT cast(volume as varchar) FROM @colTable WHERE rownum = @i) + 
             ' AS "' + 
             (SELECT columnName FROM @colTable WHERE rownum = @i) + '(Volume)"'
    SET @i = @i + 1
END
exec(@query)

结果

| AB(VALUE) | AB(VOLUME) | BB(VALUE) | BB(VOLUME) |
|-----------|------------|-----------|------------|
|         4 |          5 |         1 |          3 |
于 2013-09-25T14:20:07.043 回答