假设我有下表:
+---------+------+-------------+-----+-------+--------+
| 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 |
+---------+-------+--------------+------+--------+---------+-------+--------------+------+--------+---------+
注意我正在寻找静态/预定义数量的列,而不是基于订单项的动态。
答案 0 :(得分:2)
如果要将有限数量的值转换为列,则可以使用带有CASE表达式和聚合函数的row_number()
轻松完成此操作:
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;
但是如果您想使用PIVOT函数来获取结果,那么您需要查看多列的取消隐藏(item
,description
,qty
,price
和amount
)首先,然后应用数据透视功能。使用PIVOT的代码类似于:
;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 |