[英]SQL Server : turning rows into columns (pivot, but with a twist)
我正在尝试将表的多行压缩为1行但多列。
我看了几种方法,但是似乎没有一种方法适合我的需求。 (主要)问题是表中没有“标题”数据,这破坏了数据透视方法。
基本上,我有2个表要加入,我只想获取前3个项目(超过3个我不在乎)。
因此,我的2个表已创建并填充。
CREATE TABLE [order] ( ID INT )
CREATE TABLE OrderItem ( OrderID INT, Item VARCHAR(20) )
insert into [order] values (1)
insert into [order] values (2)
insert into orderitem values (1, 'Hammer')
insert into orderitem values (2, 'Spoon')
insert into orderitem values (2, 'Potato')
insert into orderitem values (2, 'shed')
我想要这样的结果:
ID Item1 Item2 Item3
1 Hammer NULL NULL
2 Potato shed Spoon
我研究了几种使用PIVOT
方法,但是由于每个值没有任何“标题”,并且[OrderItem]
中有成千上万个唯一的[Item]
值,我无法弄清楚如何获取查询以执行我想要的操作。
我设法通过一些难看的排名联接来做到这一点的唯一方法-效果很好,但速度慢得令人难以置信 。
(没有联接的查询需要花费一秒钟的时间才能完成,但是由于要查看的数据量大,一旦包含这些查询,则需要花费2-3分钟的时间)
SELECT
o.ID, i1.Item, i2.Item, i3.Item
FROM
[order] o
LEFT OUTER JOIN
(SELECT
*,
RANK() OVER (PARTITION BY orderId ORDER BY item) AS iRank
FROM
OrderItem) AS i1 ON i1.OrderID = o.ID AND i1.iRank = 1
LEFT OUTER JOIN
(SELECT
*,
RANK() OVER (PARTITION BY orderId ORDER BY item) AS iRank
FROM
OrderItem) AS i2 ON i2.OrderID = o.ID AND i2.iRank = 2
LEFT OUTER JOIN
(SELECT
*,
RANK() OVER (PARTITION BY orderId ORDER BY item) AS iRank
FROM
OrderItem) AS i3 ON i3.OrderID = o.ID AND i2.iRank = 3
谁能推荐一种更好的方法来查看它,使其在运行时不会完全杀死我的数据库?
尽管您可以使用pivot
做到这一点,但仅使用条件聚合可能会更容易:
select oi.OrderId,
max(case when iRank = 1 then oi.Item end) as item1,
max(case when iRank = 2 then oi.Item end) as item2,
max(case when iRank = 3 then oi.Item end) as item3
from (select oi.*,
rank() over (partition by orderId order by item) as iRank
from OrderItem oi
) oi
group by oi.OrderId;
更新-由于订单项的数量不确定,我将其转换为动态PIVOT
DECLARE @qu NVARCHAR(MAX), @pcol NVARCHAR(MAX)
SELECT @pcol= COALESCE(@pcol + ',','') + ItemNumber FROM
(SELECT DISTINCT N'Item'+ CAST (ROW_NUMBER() OVER(PARTITION BY OrderID Order by Item) AS NVARCHAR(25)) AS ItemNumber
FROM OrderItem) A
SET @qu=N'SELECT OrderId,'+ @pcol + N' FROM
(
SELECT
OrderID,N''Item''+ CAST (ROW_NUMBER() OVER(PARTITION BY OrderID Order by Item) AS NVARCHAR(25)) AS ItemNumber, Item FROM OrderItem
)S
PIVOT
(
MAX(Item)
FOR ItemNumber IN ('+@pcol +N')) AS piv'
EXEC sp_executesql @qu
更新SQL小提琴链接: http ://sqlfiddle.com/#!6/ 0cd9d0/17
编辑-原始答案:
将Pivot用于已知的最大订单项数,这可以像
SELECT OrderId,[Item1],[Item2],[Item3],[Item4],[Item5],[Item6] FROM ( SELECT OrderID,N'Item'+ CAST (ROW_NUMBER() OVER(PARTITION BY OrderID Order by Item) AS NVARCHAR(25)) AS ItemNumber, Item FROM OrderItem )S PIVOT ( MAX(Item) FOR ItemNumber IN ([Item1],[Item2],[Item3],[Item4],[Item5],[Item6]) )piv
SQL小提琴链接: http ://sqlfiddle.com/#!6/0cd9d0/4
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.