【问题标题】:How to pivot on multiple columns [closed]如何在多列上进行旋转[关闭]
【发布时间】:2013-11-26 08:03:38
【问题描述】:

我正在尝试创建一个 SQL 语句,以将可变数量的行(最多 5 行)转换为单行。一小部分数据如下所示:

+--------------+--------+-------+-------+
|      ID      | ItemID | Style |  Qty  |
+--------------+--------+-------+-------+
| 00001-5A-2XL | F911-5 | F911  | 1.566 |
| 00001-5A-2XL | 233-5  | 233   | 0.236 |
| 00001-5A-3XL | F911-5 | F911  | 1.697 |
| 00001-5A-3XL | 233-5  | 233   | 0.237 |
| 00001-5A-4XL | F911-5 | F911  | 1.833 |
| 00001-5A-4XL | 233-5  | 233   | 0.239 |
| 00001-5A-L   | F911-5 | F911  | 1.307 |
| 00001-5A-L   | 233-5  | 233   | 0.234 |
+--------------+--------+-------+-------+

我想将数据转换为如下所示:

+--------------+------+--------+-----+--------+----+--------+----+--------+----+--------+
|      ID      |  S1  | S1_Qty | S2  | S2_Qty | S3 | S3_Qty | S4 | S4_Qty | S5 | S5_Qty |
+--------------+------+--------+-----+--------+----+--------+----+--------+----+--------+
| 00001-5A-2XL | F911 | 1.566  | 233 | 0.236  |    |        |    |        |    |        |
| 00001-5A-3XL | F911 | 1.566  | 233 | 0.237  |    |        |    |        |    |        |
| 00001-5A-4XL | F911 | 1.566  | 233 | 0.239  |    |        |    |        |    |        |
| 00001-5A-L   | F911 | 1.566  | 233 | 0.234  |    |        |    |        |    |        |
+--------------+------+--------+-----+--------+----+--------+----+--------+----+--------+

在旋转时我有点迷茫,特别是当我想将StyleQuantity 都旋转到我的列中时。最多有 5 种样式(行)需要翻译成最多 5 列。

任何建议、指针等将不胜感激。

【问题讨论】:

  • 是否需要将相同的样式放入同一列?
  • 不,事实上,它不需要,因为我想要第一列中的最高数量,然后第二列中的下一个最高数量等等......直到最低数量,最多 5样式/数量对。

标签: sql sql-server-2005 pivot


【解决方案1】:

根据您的需要,您可以通过几种不同的方式获得结果。

是否需要使用两个不同的聚合来获得结果不是很清楚。如果您可能需要sum(qty),然后在style 上使用max(),我建议使用带有CASE 表达式的聚合函数来获得结果:

select id,
  max(case when ItemID = 'F911-5' then Style end) Style1,
  sum(case when ItemID = 'F911-5' then Qty else 0 end) Qty1,
  max(case when ItemID = '233-5' then Style end) Style2,
  sum(case when ItemID = '233-5' then Qty else 0 end) Qty2
from yourtable
group by id;

SQL Fiddle with Demo。然后,当您有新的 ItemId 值时,您只需添加新列。

您也可以使用 PIVOT 函数,但由于您需要在两列上进行 PIVOT,我将首先取消旋转 styleQty 列。这会将您的多列数据转换为多行,您可以使用 UNPIVOT 函数或 CROSS APPLY 获得结果 - 基本语法为:

select id, 
  col = col+cast(seq as varchar(10)), value
from
(
  select id, itemid, style, qty,
    row_number() over(partition by id
                      order by qty desc) seq
  from yourtable
) src
cross apply
(
  select 'style', style union all
  select 'qty', cast(qty as varchar(10))
) c(col, value)

SQL Fiddle with Demo。这会将您的数据转换为多行,然后可以进行透视:

|           ID |    COL |   VALUE |
|--------------|--------|---------|
| 00001-5A-2XL | style1 |    F911 |
| 00001-5A-2XL |   qty1 | 1.56600 |
| 00001-5A-2XL | style2 |     233 |
| 00001-5A-2XL |   qty2 | 0.23600 |
| 00001-5A-3XL | style1 |    F911 |

然后你可以应用 PIVOT 函数得到最终结果:

select id, style1, qty1, style2, qty2
from
(
  select id, 
    col = col+cast(seq as varchar(10)), value
  from
  (
    select id, itemid, style, qty,
      row_number() over(partition by id
                        order by qty desc) seq
    from yourtable
  ) src
  cross apply
  (
    select 'style', style union all
    select 'qty', cast(qty as varchar(10))
  ) c(col, value)
) d
pivot
(
  max(value)
  for col in (style1, qty1, style2, qty2)
) piv;

SQL Fiddle with Demo。最后,如果您有未知数量的值,那么您可以使用动态 SQL 来获取结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(seq as varchar(10)))
                    from 
                    (
                      select row_number() over(partition by id
                                                order by qty desc) seq
                      from yourtable
                    ) t
                    cross apply
                    (
                      select 'style', 1 union all
                      select 'qty', 2
                    ) c (col, so)
                    group by col, so, seq
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, ' + @cols + ' 
             from 
             (
                select id, 
                  col = col+cast(seq as varchar(10)), value
                from
                (
                  select id, itemid, style, qty,
                    row_number() over(partition by id
                                      order by qty desc) seq
                  from yourtable
                ) src
                cross apply
                (
                  select ''style'', style union all
                  select ''qty'', cast(qty as varchar(10))
                ) c(col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

SQL Fiddle with Demo。这些给出了一个结果:

|           ID | STYLE1 |    QTY1 | STYLE2 |    QTY2 |
|--------------|--------|---------|--------|---------|
| 00001-5A-2XL |   F911 | 1.56600 |    233 | 0.23600 |
| 00001-5A-3XL |   F911 | 1.69700 |    233 | 0.23700 |
| 00001-5A-4XL |   F911 | 1.83300 |    233 | 0.23900 |
|   00001-5A-L |   F911 | 1.30700 |    233 | 0.23400 |

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    相关资源
    最近更新 更多