SQL Pivot двойная сумма - PullRequest
       22

SQL Pivot двойная сумма

0 голосов
/ 05 июня 2019

У меня есть следующий результат запроса:

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 ??

Альтернативные

Я использовал другую альтернативу, применяя OUTER APPLY:

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 Ответ

1 голос
/ 05 июня 2019

Вы сможете легко получить общее 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 данные будут иметь то же значение, прежде чем вы примените аспект GROUP BY функции PIVOT.

...