SQL Server:将行转换为列(枢轴,但有扭曲)
我试图将表中的多行压缩为一行多列 我看了一些方法,但没有一种适合我的需要。 (主要)问题是表中没有“标题”数据,这会破坏pivot方法 基本上,我有两个表,我正试图加入,我试图得到只有前3项(任何超过3我不关心) 因此,我的两个表被创建并填充SQL Server:将行转换为列(枢轴,但有扭曲),sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我试图将表中的多行压缩为一行多列 我看了一些方法,但没有一种适合我的需要。 (主要)问题是表中没有“标题”数据,这会破坏pivot方法 基本上,我有两个表,我正试图加入,我试图得到只有前3项(任何超过3我不关心) 因此,我的两个表被创建并填充 CREATE TABLE [order] ( ID INT ) CREATE TABLE OrderItem ( OrderID INT, Item VARCHAR(20) ) insert into [order] values (1) insert
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分钟以上的时间,因为它所查看的数据量很大)
有谁能推荐一种更好的方法,在运行我的数据库时不会完全杀死它吗?尽管可以使用
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
,但只使用条件聚合可能更容易:
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;
更新-由于订单项目的数量是不确定的,所以我将其转换为动态透视
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 FIDLE链接:
编辑-原始答案:
使用已知最大订单项目数的Pivot,可以做到这一点
像
Sql fiddle链接:
更新-由于订单项目的数量是不确定的,所以我将其转换为动态透视
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 FIDLE链接:
编辑-原始答案:
使用已知最大订单项目数的Pivot,可以做到这一点
像
Sql fiddle链接: