SQL Server:将行转换为列(枢轴,但有扭曲)

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

我试图将表中的多行压缩为一行多列

我看了一些方法,但没有一种适合我的需要。 (主要)问题是表中没有“标题”数据,这会破坏pivot方法

基本上,我有两个表,我正试图加入,我试图得到只有前3项(任何超过3我不关心)

因此,我的两个表被创建并填充

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链接: