1

假设我有下表:

+---------+------+-------------+-----+-------+--------+
| invoice | item | description | qty | price | amount |
+---------+------+-------------+-----+-------+--------+
|    1234 | L    | labour      |   1 |    50 |     50 |
|    1234 | P    | parts       |   2 |   100 |    200 |
|    9865 | L    | labour      |   1 |    25 |     25 |
|    9865 | P    | parts       |   1 |    25 |     25 |
|    5555 | P    | parts       |   2 |   100 |    200 |
+---------+------+-------------+-----+-------+--------+

我想要一个选择查询,它将 2 行转换为每个唯一发票编号的列,以便每个发票编号只有一行。

所以对于上面的例子,我期望以下:

+---------+-------+--------------+------+--------+---------+-------+--------------+------+--------+---------+
| invoice | item1 | description1 | qty1 | price1 | amount1 | item2 | description2 | qty2 | price2 | amount2 |
+---------+-------+--------------+------+--------+---------+-------+--------------+------+--------+---------+
|    1234 | L     | labour       |    1 |     50 |      50 | P     | parts        | 2    | 100    | 200     |
|    9865 | L     | labour       |    1 |     25 |      25 | P     | parts        | 1    | 25     | 25      |
|    5555 | P     | parts        |    2 |    100 |     200 | NULL  | NULL         | NULL | NULL   | NULL    |
+---------+-------+--------------+------+--------+---------+-------+--------------+------+--------+---------+

注意我正在寻找静态/预定义的列数,而不是基于行项目的动态。

4

1 回答 1

2

如果要转换为列的值数量有限,则可以使用row_number()CASE 表达式和聚合函数轻松完成此操作:

select invoice,
  max(case when seq = 1 then item end) item1,
  max(case when seq = 1 then description end) description1,
  max(case when seq = 1 then qty end) qty1,
  max(case when seq = 1 then price end) price1,
  max(case when seq = 1 then amount end) amount1,
  max(case when seq = 2 then item end) item2,
  max(case when seq = 2 then description end) description2,
  max(case when seq = 2 then qty end) qty2,
  max(case when seq = 2 then price end) price2,
  max(case when seq = 2 then amount end) amount2
from 
(
  select invoice, item, description, qty, price, amount,
    row_number() over(partition by invoice order by invoice) seq
  from yourtable
) d
group by invoice;

请参阅SQL Fiddle with Demo

但是,如果您想使用PIVOT函数来获得结果,那么您将需要先查看取消透视多个列(itemdescription、和) qty,然后再应用 pivot 函数。使用 PIVOT 的代码将类似于:priceamount

;with cte as
(
  select invoice, item, description, qty, price, amount,
    row_number() over(partition by invoice order by invoice) seq
  from yourtable
)
select invoice,
  item1, description1, qty1, price1, amount1,
  item2, description2, qty2, price2, amount2
from
(
  select invoice, 
    col = col+cast(seq as varchar(10)), 
    value
  from cte
  cross apply
  (
    select 'item', item union all
    select 'description', description union all
    select 'qty', cast(qty as varchar(50)) union all
    select 'price', cast(price as varchar(50)) union all
    select 'amount', cast(amount as varchar(50))
  ) c (col, value)
) d
pivot
(
  max(value)
  for col in (item1, description1, qty1, price1, amount1,
              item2, description2, qty2, price2, amount2)
) piv;

请参阅SQL Fiddle with Demo。两者都会给出结果:

| INVOICE | ITEM1 | DESCRIPTION1 | QTY1 | PRICE1 | AMOUNT1 |  ITEM2 | DESCRIPTION2 |   QTY2 | PRICE2 | AMOUNT2 |
|    1234 |     L |       labour |    1 |     50 |      50 |      P |        parts |      2 |    100 |     200 |
|    5555 |     P |        parts |    2 |    100 |     200 | (null) |       (null) | (null) | (null) |  (null) |
|    9865 |     L |       labour |    1 |     25 |      25 |      P |        parts |      1 |     25 |      25 |
于 2013-09-04T16:23:12.190 回答