SQL Pivot双重和

时间:2019-06-05 13:19:35

标签: sql-server-2012 sum pivot

我有以下查询结果:

dday         showtime             qty    total
2019-06-03   Sat 22/6 - 2:30 PM   1      50.00
2019-06-03   Sat 22/6 - 7:00 PM   1      50.00
2019-06-04   NULL                 NULL   NULL

我想对此进行透视并显示一个新结果,将放映时间作为列,将“数量”和每“日”的总数相加,如下所示:

DAY     [Fri 21/6 - 7:00 PM]   [Sat 22/6 - 2:30 PM]   [Sat 22/6 - 7:00 PM]   TICKETS   AMOUNT
Jun 3   0                      1                      1                      2         100.00
Jun 4   0                      0                      0                      0         NULL

我正在使用此查询:

SELECT
    CONVERT(CHAR(4), dday, 0) + CAST(DAY(dday) AS VARCHAR) 'DAY'
    , SUM(ISNULL([Thu 20/6  - 7:00 PM],0)) [Thu 20/6  - 7:00 PM],SUM(ISNULL([Fri 21/6  - 7:00 PM],0)) [Fri 21/6  - 7:00 PM],SUM(ISNULL([Sat 22/6  - 2:30 PM],0)) [Sat 22/6  - 2:30 PM],SUM(ISNULL([Sat 22/6  - 7:00 PM],0)) [Sat 22/6  - 7:00 PM]
    , SUM(ISNULL([Thu 20/6  - 7:00 PM],0)+ISNULL([Fri 21/6  - 7:00 PM],0)+ISNULL([Sat 22/6  - 2:30 PM],0)+ISNULL([Sat 22/6  - 7:00 PM],0)) 'TICKETS'
    , SUM(total) 'AMOUNT'
FROM   z
PIVOT
(
    MAX(qty)
    FOR showtime IN ([Thu 20/6  - 7:00 PM],[Fri 21/6  - 7:00 PM],[Sat 22/6  - 2:30 PM],[Sat 22/6  - 7:00 PM])
) AS P 
GROUP BY dday
ORDER BY dday   

但是我得到这个结果:

DAY     [Fri 21/6 - 7:00 PM]   [Sat 22/6 - 2:30 PM]   [Sat 22/6 - 7:00 PM]   TICKETS   AMOUNT
Jun 3   0                      1                      1                      2         50.00
Jun 4   0                      0                      0                      0         NULL

数量“票”的总和是正确的,但是为什么总和显示50.00而不是100.00?

替代

我使用了另一种方法,应用外部应用:

SELECT
     CONVERT(CHAR(4), dday, 0) + CAST(DAY(dday) AS VARCHAR) 'DAY'
    , SUM(ISNULL([Thu 20/6  - 7:00 PM],0)) [Thu 20/6  - 7:00 PM],SUM(ISNULL([Fri 21/6  - 7:00 PM],0)) [Fri 21/6  - 7:00 PM],SUM(ISNULL([Sat 22/6  - 2:30 PM],0)) [Sat 22/6  - 2:30 PM],SUM(ISNULL([Sat 22/6  - 7:00 PM],0)) [Sat 22/6  - 7:00 PM]
    , SUM(ISNULL([Thu 20/6  - 7:00 PM],0)+ISNULL([Fri 21/6  - 7:00 PM],0)+ISNULL([Sat 22/6  - 2:30 PM],0)+ISNULL([Sat 22/6  - 7:00 PM],0)) 'TICKETS'
    , SUPERTOTAL 'AMOUNT'
FROM   z AS j
OUTER APPLY
 ( 
    SELECT SUM(total) 'SUPERTOTAL'
    FROM z AS x
    WHERE x.dday = j.dday
 ) x
PIVOT
(
    MAX(qty)
    FOR showtime IN ([Thu 20/6  - 7:00 PM],[Fri 21/6  - 7:00 PM],[Sat 22/6  - 2:30 PM],[Sat 22/6  - 7:00 PM])
) AS P 
GROUP BY dday, SUPERTOTAL
ORDER BY dday

在那种情况下,它可以工作,但是我真的需要为每个额外的总和应用这个“子查询”吗?可以一次实现我期望的结果吗?

1 个答案:

答案 0 :(得分:1)

通过向查询中添加两次使用窗口函数的功能,您应该能够轻松获得总体Total以及Tickets总数。如果您对查询使用sum(<col>) over(partition by <col>),则可以简化操作。

例如,如果您的表是:

CREATE TABLE yourtable
    ([dday] datetime, [showtime] varchar(18), [qty] int, [total] decimal(10,2))
;

INSERT INTO yourtable
    ([dday], [showtime], [qty], [total])
VALUES
    ('2019-06-03 00:00:00', 'Sat 22/6 - 2:30 PM', 8017, 50.00),
    ('2019-06-03 00:00:00', 'Sat 22/6 - 7:00 PM', 5019, 50.00),
    ('2019-06-04 00:00:00', NULL, NULL, NULL);

您可以将查询更改为:

select 
    CONVERT(CHAR(4), dday, 0) + CAST(DAY(dday) AS VARCHAR) 'DAY'
    ,ISNULL([Thu 20/6  - 7:00 PM],0) [Thu 20/6  - 7:00 PM]
    ,ISNULL([Fri 21/6  - 7:00 PM],0) [Fri 21/6  - 7:00 PM]
    ,ISNULL([Sat 22/6  - 2:30 PM],0) [Sat 22/6  - 2:30 PM]
    ,ISNULL([Sat 22/6  - 7:00 PM],0) [Sat 22/6  - 7:00 PM]
    , Isnull(Tickets, 0) Tickets
    , IsNull(Total, 0) Total
from
(
    SELECT 
        dday,
        showtime, 
        qty,
        Tickets= sum(qty) over(partition by dday),
        Total = sum(Total) over(partition by dday)
    FROM   yourtable
) d
PIVOT
(
    MAX(qty)
    FOR showtime IN ([Thu 20/6  - 7:00 PM],[Fri 21/6  - 7:00 PM],[Sat 22/6  - 2:30 PM],[Sat 22/6  - 7:00 PM])
) AS P 

区别在于我使用的子查询内部:

Tickets= sum(qty) over(partition by dday),
Total = sum(Total) over(partition by dday)

这将为每个dday创建票证和总计,如果您在PIVOT之前使用此数据,则在应用{{1 GROUP BY函数的}}方面。