SQL Server 以 2 个(或多个)聚合为中心

Gor*_*ord 3 sql sql-server pivot

是否可以对 SQL Server 中的多个聚合列进行透视?我有以下订单表:

[ORDERS]
| CustName | OrderedProduct | QtyOrdered | UnitCost | UnitPrice |  OrderDate
  Bob      | Canned Tuna    |          6 |       11 |        14 | 21-12-2016 13:11:00
  Steve    | Canned Salmon  |          2 |       15 |        19 | 03-11-2016 11:03:00
  Bob      | Canned Tuna    |         10 |       10 |        13 | 22-12-2016 10:43:00
  Bob      | Canned Tuna    |          4 |        9 |        10 | 13-11-2016 17:22:00
Run Code Online (Sandbox Code Playgroud)

我有以下数据透视查询,它为我提供了每个客户在 11 月/12 月几个月内每个产品的订单数量:

SELECT CustName, OrderedProduct, [VOL Dec 2016], [VOL Nov 2016] FROM
(
    SELECT CustName, OrderedProduct, QtyOrdered,
    'VOL ' + CONVERT(CHAR(4), OrderDate, 100) + CONVERT(CHAR(4), OrderDate, 120) AS YearMonthVol
    FROM [ORDERS]
) src
PIVOT
(
    SUM(QtyOrdered)
    FOR YearMonthVol IN ([VOL Dec 2016], [VOL Nov 2016])
) pvtvol
WHERE CustName='Bob'
Run Code Online (Sandbox Code Playgroud)

这给出了预期的结果

CustName | OrderedProduct | VOL Dec 2016 | VOL Nov 2016
Bob      | Canned Tuna    |           16 |            4
Run Code Online (Sandbox Code Playgroud)

我想要的是也以边距为中心,因此将src查询更改为:

    SELECT CustName, OrderedProduct, QtyOrdered,
    ((UnitPrice-UnitCost)*QtyOrdered) AS Margin,
    'VOL ' + CONVERT(CHAR(4), OrderDate, 100) + CONVERT(CHAR(4), OrderDate, 120) AS YearMonthVol
    'MAR ' + CONVERT(CHAR(4), OrderDate, 100) + CONVERT(CHAR(4), OrderDate, 120) AS YearMonthMar
    FROM [ORDERS]
Run Code Online (Sandbox Code Playgroud)

我尝试了以下修改后的查询添加第二个数据透视表

SELECT CustName, OrderedProduct, [VOL Dec 2016], [VOL Nov 2016], [MAR Dec 2016], [MAR Nov 2016] FROM
(
    SELECT CustName, OrderedProduct, QtyOrdered,
    ((UnitPrice-UnitCost)*QtyOrdered) AS Margin,
    'VOL ' + CONVERT(CHAR(4), OrderDate, 100) + CONVERT(CHAR(4), OrderDate, 120) AS YearMonthVol
    'MAR ' + CONVERT(CHAR(4), OrderDate, 100) + CONVERT(CHAR(4), OrderDate, 120) AS YearMonthMar
    FROM [ORDERS]
) src
PIVOT
(
    SUM(QtyOrdered)
    FOR YearMonthVol IN ([VOL Dec 2016], [VOL Nov 2016])
) pvtvol
PIVOT
(
    SUM(Margin)
    FOR YearMonthMar IN ([MAR Dec 2016], [MAR Nov 2016])
) pvtmar
WHERE CustName='Bob'
Run Code Online (Sandbox Code Playgroud)

我想表的处置看到的是

CustName | OrderedProduct | VOL Dec 2016 | VOL Nov 2016 | MAR Dec 2016 | MAR Nov 2016
Bob      | Canned Tuna    |           16 |            4 |           48 |            4
Run Code Online (Sandbox Code Playgroud)

实际看到的表是

CustName | OrderedProduct | VOL Dec 2016 | VOL Nov 2016 | MAR Dec 2016 | MAR Nov 2016
Bob      | Canned Tuna    |           16 |         NULL |           48 |         NULL
Bob      | Canned Tuna    |         NULL |            4 |         NULL |            4
Run Code Online (Sandbox Code Playgroud)

因此,似乎没有应用保证金的支点,每个订单我都会得到一行。我试图用我尝试使用的方法实现的目标实际上是可能的,还是我最好使用 VOL 和 MAR 的交叉表查询或数据透视表和交叉表的混合(VOL 的数据透视表,MAR 的交叉表? )

非常感谢任何建议。

Joh*_*tti 6

您可以稍微简化一下查询

例子

Select *
 From (
        Select A.CustName 
              ,A.OrderedProduct
              ,B.*
         From  ORDERS A
         Cross Apply ( values ('VOL '+left(DateName(Month,OrderDate),3)+' '+DateName(Year,OrderDate), QtyOrdered )
                             ,('MAR '+left(DateName(Month,OrderDate),3)+' '+DateName(Year,OrderDate),((UnitPrice-UnitCost)*QtyOrdered) )
                     ) B (Item,Value)
         Where CustName='Bob'
      ) A
 Pivot (sum([Value]) For [Item] in ([VOL Dec 2016], [VOL Nov 2016],[MAR Dec 2016], [MAR Nov 2016]) ) p
Run Code Online (Sandbox Code Playgroud)

退货

在此处输入图片说明