Oracle SQL - Группировка по промежуточной сумме MTD и итоговому итогу с начала года - PullRequest
1 голос
/ 08 апреля 2020

У меня есть запрос, который возвращает данные, сгруппированные по концу месяца для дат прошлого месяца, но по дате для дат MTD. Я могу использовать group by ROLLUP () для успешной генерации итоговой суммы, но я также хотел бы рассчитать итоговую сумму MTD.

Используя следующий запрос:

select 

COALESCE(to_char(case when postdate < trunc(sysdate,'MM')
  then last_day(postdate)
  else postdate end,'mm/dd/yyyy'),'Grand Total') MonthEnd, 
count(colA) NumColA, 
count(colB) NumColB,
count(colC) NumColC

from Table1

where postdate >= trunc(sysdate,'YY') and postdate < trunc(sysdate,'DD')

GROUP BY ROLLUP 
(
COALESCE(to_char(case when postdate < trunc(sysdate,'MM')
  then last_day(postdate)
  else postdate end,'mm/dd/yyyy'),'Grand Total')
)

Какие дает мне (ожидаемый) результат:

Month End   NumColA NumColB NumColC
1/31/2020   10  25  100
2/29/2020   10  35  150
3/31/2020   10  40  300
4/1/2020    1   3   61
…           
4/7/2020    4   8   11
Grand Total 35  111 622

То, что я хочу увидеть, является промежуточным итогом MTD за апрель только до общего итога, например:

Month End   NumColA NumColB NumColC
1/31/2020   10  25  100
2/29/2020   10  35  150
3/31/2020   10  40  300
4/1/2020    1   3   61
…           
4/7/2020    4   8   11
MTD         5   11  72
Grand Total 35  111 622

Извинения за паршивый интервал между столами.

1 Ответ

0 голосов
/ 08 апреля 2020

GROUPING SETS и функции GROUPING_ID могут помочь здесь.

with t (MonthEnd, NumColA, NumColB, NumColC) as ( 
  select to_date('1/31/2020', 'mm/dd/yyyy'),   10,  25,  100 from dual union all
  select to_date('2/29/2020', 'mm/dd/yyyy'),   10,  35,  150 from dual union all
  select to_date('3/31/2020', 'mm/dd/yyyy'),   10,  40,  300 from dual union all
  select to_date('4/1/2020',  'mm/dd/yyyy'),    1,   3,   61 from dual union all 
  select to_date('4/2/2020',  'mm/dd/yyyy'),    5,   9,   08 from dual union all
  select to_date('4/7/2020',  'mm/dd/yyyy'),    4,   8,   11 from dual
)
, prep as (
  select MonthEnd
  , case when trunc(sysdate, 'month') = trunc(monthend, 'month') then trunc(sysdate, 'month') end grp_dt
  , NumColA, NumColB, NumColC 
  from t
)
select grouping_id (monthend, grp_dt) grp, monthend, grp_dt 
, case when grouping_id (monthend, grp_dt) = 2 and grp_dt is not null then 'MTD'
       when grouping_id (monthend, grp_dt) = 2 and grp_dt is null then 'Prev'
       when grouping_id (monthend, grp_dt) = 3 then 'Grand Total'
       else to_char(monthend, 'mm/dd/yyyy') end l
, sum(NumColA) sa, sum(numcolb) sb, sum(numcolc) sc 
from prep
group by grouping sets((monthend, grp_dt), (grp_dt), ());

       GRP MONTHEND  GRP_DT               L                   SA         SB         SC
---------- --------- -------------------- ----------- ---------- ---------- ----------
         0 31-JAN-20                      01/31/2020          10         25        100
         0 29-FEB-20                      02/29/2020          10         35        150
         0 31-MAR-20                      03/31/2020          10         40        300
         2                                Prev                30        100        550
         0 01-APR-20 01-APR-20            04/01/2020           1          3         61
         0 02-APR-20 01-APR-20            04/02/2020           5          9          8
         0 07-APR-20 01-APR-20            04/07/2020           4          8         11
         2           01-APR-20            MTD                 10         20         80
         3                                Grand Total         40        120        630

9 rows selected. 

Я сохранил все столбцы для целей отладки, и первые 3 столбца могут быть удалены из самого внешнего SELECT. Если вы не заинтересованы в отображении строки Prev, просто оберните ее другим внешним запросом и примените WHERE TXT != 'Prev'.

with t (MonthEnd, NumColA, NumColB, NumColC) as ( 
  select to_date('1/31/2020', 'mm/dd/yyyy'),   10,  25,  100 from dual union all
  select to_date('2/29/2020', 'mm/dd/yyyy'),   10,  35,  150 from dual union all
  select to_date('3/31/2020', 'mm/dd/yyyy'),   10,  40,  300 from dual union all
  select to_date('4/1/2020',  'mm/dd/yyyy'),    1,   3,   61 from dual union all 
  select to_date('4/2/2020',  'mm/dd/yyyy'),    5,   9,   08 from dual union all
  select to_date('4/7/2020',  'mm/dd/yyyy'),    4,   8,   11 from dual
)
, prep as (
  select MonthEnd
  , case when trunc(sysdate, 'month') = trunc(monthend, 'month') then trunc(sysdate, 'month') end grp_dt
  , NumColA, NumColB, NumColC 
  from t
)
select txt, sa, sb, sc from (
  select grouping_id (monthend, grp_dt) grp, monthend, grp_dt 
  , case when grouping_id (monthend, grp_dt) = 2 and grp_dt is not null then 'MTD'
         when grouping_id (monthend, grp_dt) = 2 and grp_dt is null then 'Prev'
         when grouping_id (monthend, grp_dt) = 3 then 'Grand Total'
         else to_char(monthend, 'mm/dd/yyyy') end txt
  , sum(NumColA) sa, sum(numcolb) sb, sum(numcolc) sc 
  from prep
  group by grouping sets((monthend, grp_dt), (grp_dt), ())
)
where txt != 'Prev'
order by grp, monthend;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...