【问题标题】:T-SQL Converting N number of rows to columnsT-SQL将N行转换为列
【发布时间】:2017-05-20 01:12:33
【问题描述】:

我正在寻找一个性能良好的 T-SQL 查询来提供大量行 N 列。但是每行的列数不会相同。

例如 - 我有一个类似以下的订单表,大约有 100 万行。

命令 订单 ID 日期 ======== ======== 1 20160102 2 20160402

每个订单可以有 N 个订单行。

我的订单表有大约 150 万行;

订单行 OrderID OrderLine ProductID 金额 ==================================== 1 1 3245 299.00 2 1 9876 799.00 2 2 5466 899.00 2 3 7752 599.00

我想要如下的最终结果:

OrderID 日期 ProductID1 Amount1 ProductID2 Amount2 ProductID3 Amount3 =================================================== ========== ======= 1 20160102 3245 299.00 2 20160402 9876 799.00 5466 899.00 7752 599.00

每个订单的订单行数可以很大(例如 50 个)。

我想我可以使用子选择,但这需要 N 个子选择 - 而且效果会很差

选择 订单号, 日期, (SELECT ProductID from ORDERLINE OI JOIN O ON O.OrderID=OI.OrderID WHERE ORDERLINE=1) AS ProductID1, (SELECT Amount FROM ORDERLINE OI JOIN O ON O.OrderID=OI.OrderID WHERE ORDERLINE=1) 作为 Amount1, ... (SELECT ProductID from ORDERLINE OI JOIN O ON O.OrderID=OI.OrderID WHERE ORDERLINE=N) AS ProductIDN, (SELECT Amount FROM ORDERLINE OI JOIN O ON O.OrderID=OI.OrderID WHERE ORDERLINE=N) AS AmountN 从 订购 O

另一个选项可能是旋转。 但在我看来——这不是“传统”的旋转——它是动态旋转。

但我不确定它的外观和性能如何?

【问题讨论】:

标签: sql sql-server


【解决方案1】:

我会推荐条件聚合:

SELECT o.OrderID, o.Date,
       MAX(CASE WHEN ol.orderline = 1 THEN ProductId END) as ProductId1,
       MAX(CASE WHEN ol.orderline = 1 THEN Amount END) as Amount1,
       MAX(CASE WHEN ol.orderline = 2 THEN ProductId END) as ProductId2,
       MAX(CASE WHEN ol.orderline = 2 THEN Amount END) as Amount2,
       . . .
FROM ORDER O JOIN
     ORDERLINE OI
     ON O.OrderID = OI.OrderID
GROUP BY o.OrderID, o.Date;

除非您有一个名为o 的表,否则我不希望您的版本能够正常工作。正确的语法是:

(SELECT ProductID FROM ORDERLINE OI WHERE O.OrderID = OI.OrderID AND ORDERLINE = 1) AS ProductID1,

【讨论】:

    【解决方案2】:

    如果你需要动态

    Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(concat('ProductID',OrderLine))+','+ QuoteName(concat('Amount',OrderLine)) From OrderLine  Order by 1 For XML Path('')),1,1,'') 
    Select  @SQL = '
    Select [OrderID],[Date],' + @SQL + '
    From (
            Select A.OrderID
                  ,A.Date
                  ,C.*
            From   [Order] A
            Join   OrderLine B on (A.OrderID=B.OrderID)
            Cross  Apply (Values (concat(''ProductID'',B.OrderLine),cast(B.ProductID as varchar(25)))
                                ,(concat(''Amount''   ,B.OrderLine),cast(B.Amount as varchar(25)))
                          ) C (Item,Value)
    
         ) A
     Pivot (max(Value) For [Item] in (' + @SQL + ') ) p'
    Exec(@SQL);
    

    返回

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-06
      • 2021-02-15
      • 2012-03-08
      • 2020-11-19
      • 2013-06-21
      • 2013-11-08
      相关资源
      最近更新 更多