[英]Oracle SQL - Group by Rollup MTD Subtotal and YTD Grand Total
我有一个查询,它返回按月末分组的上个月日期的数据,但按日期分组的 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
我想看到的是 4 月 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
为糟糕的表格间距道歉。
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.