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

时间:2015-07-27 16:13:10

标签: sql sql-server sql-server-2008

我正在尝试将表的多行压缩为1行但多列。

我看了几个方法,但似乎没有一个方法适合我的需要。 (主要)问题是表中没有“标题”数据,这会破坏枢轴方法。

基本上我有两张桌子,我想加入,我只想获得前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的方法,但因为我没有为每个值设置任何“标题”,并且因为有数千个可能的唯一[Item][OrderItem]我无法弄清楚如何让查询做我想做的事。

我设法用一些丑陋的排名连接来做到这一点的唯一方法 - 效果很好但是非常慢

(没有连接的查询只需要几分之一秒即可完成,但由于其查看的数据量,一旦包含它们,则需要花费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

任何人都可以推荐一种更好的方法来查看在运行时不会完全杀死我的数据库吗?

2 个答案:

答案 0 :(得分:2)

虽然您可以使用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;

答案 1 :(得分:2)

更新 - 由于订单商品的数量不确定,我将其转换为动态PIVOT

React.Children.map(this.props.children, function (child) {
  return React.cloneElement(child, {
    someProperty: this.props.someProperty
  });
});

更新SQL小提琴链接:http://sqlfiddle.com/#!6/0cd9d0/17

编辑 - 原始答案:

  

将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/4