СУБТОТАЛЫ ГРУППЫ ПО В ОРАКУЛЕ - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть таблица.

TASK_CD    |  STATUS | DUE_DATE
----------------------------------
T0001      |  NW     | SYSDATE + 1
T0001      |  IP     | SYSDATE 
T0001      |  AG     | SYSDATE
T0002      |  NW     | SYSDATE - 1
T0002      |  NW     | SYSDATE - 2
T0003      |  AG     | SYSDATE + 1

У меня сейчас запрос

select TASK_CD, STATUS, SUM(1) TOTALS, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) FUTURE, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) TODAY, 
SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) OVERDUE, 
FROM TM_TASK GROUP BY TASK_CD, STATUS;

Результат будет

TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE
----------------------------------------------------
T0001   | NW     | 1      | 1      | 0     | 0
T0001   | IP     | 1      | 0      | 1     | 0
T0001   | AG     | 1      | 0      | 1     | 0
T0002   | NW     | 2      | 0      | 0     | 2
T0003   | AG     | 1      | 1      | 0     | 0

При удаленииСОСТОЯНИЕ от выбора и группы, я получаю

TASK_CD | TOTALS | FUTURE | TODAY | OVERDUE
-----------------------------------------------
T0001   | 3      | 1      | 2     | 0
T0002   | 2      | 0      | 0     | 2
T0003   | 1      | 1      | 0     | 0

Есть ли способ объединить оба и объединить результаты, давая мне TOTALS_ALL, FUTURE_TOTALS, OVERDUE_TOTALS, TODAY_TOTALS, где это суммы, когда статус не рассматривается дляGROUP BY

TASK_CD | STATUS | TOTALS | FUTURE | TODAY | OVERDUE| TOTALS_ALL | FUTURE_TOTAL | TODAY_TOTAL | OVERDUE_TOTAL
T0001   | NW     | 1      | 1      | 0     | 0      | 3          | 1
             | 2           | 0
T0001   | IP     | 1      | 0      | 1     | 0      | 3          | 1
             | 2           | 0
T0001   | AG     | 1      | 0      | 1     | 0      | 3          | 1
             | 2           | 0
T0002   | NW     | 2      | 0      | 0     | 2      | 2          | 0
             | 0           | 2
T0003   | AG     | 1      | 1      | 0     | 0      | 1          | 1
             | 0           | 0

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Вы бы использовали оконные функции:

select TASK_CD, STATUS, SUM(1) TOTALS, 
       SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end) as FUTURE, 
       SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end) as TODAY, 
       SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end) as OVERDUE, 
       SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) > SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_FUTURE, 
       SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) = SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_TODAY, 
       SUM(SUM(CASE WHEN (TRUNC(DUE_DATE ) < SYSDATE) then 1 else 0 end)) OVER (PARTITION BY status) as TOTAL_OVERDUE
FROM TM_TASK
GROUP BY TASK_CD, STATUS;
0 голосов
/ 19 ноября 2018

Вы можете использовать условие факторинга подзапроса (более часто называемое общим табличным выражением), чтобы сгенерировать исходный набор данных, а затем аналитическую SUM() для агрегирования

with initial_totals as (
select task_cd
     , status
     , count(*) as totals
     , sum(case when due_date >= trunc(sysdate) + 1 then 1 else 0 end) as future
     , sum(case when trunc(due_date) = trunc(sysdate) then 1 else 0 end) as today
     , sum(case when due_date < trunc(sysdate) then 1 else 0 end) as overdue
  from tm_task
 group by task_cd, status
       )
select task_cd
     , status
     , future
     , today
     , overdue
     , sum(future) over (partition by task_cd) as future_total
     , sum(today) over (partition by task_cd) as today_total
     , sum(overdue) over (partition by task_cd) as overdue_total
  from initial_totals

Это ваш оригинальный запрос (слегка измененный, см. Ниже), а затем аналитическая сумма по каждому коду задачи. Аналитическая сумма равна сумме, но без сопоставления результата с каждой строкой.

Вы можете увидеть это в действии на db <> fiddle .

Вы заметите, что я изменил вашу логику дат. Это потому, что TRUNC(DUE_DATE ) > SYSDATE - это то же самое, что сказать , когда полночь сегодня больше, чем эта секунда . Я изменил это на due_date >= trunc(sysdate) + 1, то есть , когда эта секунда в или после полуночи завтра . Я изменил всю логику дат аналогичным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...