简体   繁体   English

在 oracle sql 中获取每个月的累积总和

[英]Get a cumulative sum for each month in oracle sql

Hi I have a table with 3 columns.嗨,我有一个 3 列的表。

custid  p_date          vegetable
0000009 07-APR-20       tomato
0000013 25-MAR-20       potato
0000015 11-APR-19       tomato
0000016 23-JUL-18       potato
0000019 19-JUL-18       potato
0000018 07-JUN-20       turnip
0000020 12-JUL-18       turnip
0000022 23-JUL-18       potato
0000023 12-JUL-18       turnip
0000024 11-AUG-20       potato

I need to calculate the distinct count for the customers based on the veggie column along with cumulative sum for each month我需要根据 veggie 列以及每个月的累积总和计算客户的不同计数

the output should have below columns output 应具有以下列

date        
tomato_ct 
cum_tomato_ct
potato_ct
cum_potato_ct
turnip_ct        
cum_turnip_ct

If you want monthly counts and cumulative counts pivoted by vegetable, you can do:如果您想要以蔬菜为中心的每月计数和累积计数,您可以执行以下操作:

select trunc(p_date, 'month') as p_month,
    sum(case when vegetable = 'tomato' then 1 else 0 end) as tomato_ct,
    sum(sum(case when vegetable = 'tomato' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_tomato_ct,
    sum(case when vegetable = 'potato' then 1 else 0 end) as potato_ct,
    sum(sum(case when vegetable = 'potato' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_potato_ct,
    sum(case when vegetable = 'turnip' then 1 else 0 end) as turnip_ct,
    sum(sum(case when vegetable = 'turnip' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_turnip_ct
from mytable
group by trunc(p_date, 'month')

You mentioned that you want a count of distinct customers.您提到您想要统计不同的客户。 If you want to count each customer only once par vegetable, on their earliest appearance, then I would recommend two levels of aggregation:如果您只想在他们最早出现的情况下对每个客户计算一次普通蔬菜,那么我建议使用两个级别的聚合:

select trunc(p_date, 'month') as p_month,
    sum(case when vegetable = 'tomato' then 1 else 0 end) as tomato_ct,
    sum(sum(case when vegetable = 'tomato' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_tomato_ct,
    sum(case when vegetable = 'potato' then 1 else 0 end) as potato_ct,
    sum(sum(case when vegetable = 'potato' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_potato_ct,
    sum(case when vegetable = 'turnip' then 1 else 0 end) as turnip_ct,
    sum(sum(case when vegetable = 'turnip' then 1 else 0 end)) over(order by trunc(p_date, 'month')) as cum_turnip_ct
from (
    select cust_id, vegetable, min(p_date) as p_date
    from mytable
    group by cust_id, vegetable
) t
group by trunc(p_date, 'month')

You can use the combination of analytical function and GROUP BY as follows:您可以使用analytical function 和GROUP BY的组合,如下所示:

SQL>
SQL> -- sample data
SQL> WITH YOUR_TABLE(custid,  p_date,          vegetable) AS
  2  (SELECT '0000009', TO_DATE('07-APR-20','DD-MON-RR'),       'tomato' FROM DUAL UNION ALL
  3  SELECT '0000013', TO_DATE('25-MAR-20','DD-MON-RR'),       'potato' FROM DUAL UNION ALL
  4  SELECT '0000015', TO_DATE('11-APR-19','DD-MON-RR'),       'tomato' FROM DUAL UNION ALL
  5  SELECT '0000016', TO_DATE('23-JUL-18','DD-MON-RR'),       'potato' FROM DUAL UNION ALL
  6  SELECT '0000019', TO_DATE('19-JUL-18','DD-MON-RR'),       'potato' FROM DUAL UNION ALL
  7  SELECT '0000018', TO_DATE('07-JUN-20','DD-MON-RR'),       'turnip' FROM DUAL UNION ALL
  8  SELECT '0000020', TO_DATE('12-JUL-18','DD-MON-RR'),       'turnip' FROM DUAL UNION ALL
  9  SELECT '0000022', TO_DATE('23-JUL-18','DD-MON-RR'),       'potato' FROM DUAL UNION ALL
 10  SELECT '0000023', TO_DATE('12-JUL-18','DD-MON-RR'),       'turnip' FROM DUAL UNION ALL
 11  SELECT '0000024', TO_DATE('11-AUG-20','DD-MON-RR'),       'potato' FROM DUAL)
 12  -- actual query starts from here
 13  SELECT P_DATE,
 14     COUNT(CASE WHEN vegetable = 'tomato' THEN 1 END) AS TOMATO_CT,
 15     MAX(TOMATO_CNT) AS CUM_TOMATO_CT,
 16     COUNT(CASE WHEN vegetable = 'potato' THEN 1 END) AS POTATO_CT,
 17     MAX(POTATO_CNT) AS CUM_POTATO_CT,
 18     COUNT(CASE WHEN vegetable = 'turnip' THEN 1 END) AS TURNIP_CT,
 19     MAX(TURNIP_CNT) AS CUM_TURNIP_CT
 20    FROM
 21    (SELECT T.*,
 22   COUNT(CASE WHEN vegetable = 'tomato' THEN 1 END) OVER (ORDER BY P_DATE) AS TOMATO_CNT,
 23   COUNT(CASE WHEN vegetable = 'potato' THEN 1 END) OVER (ORDER BY P_DATE) AS POTATO_CNT,
 24   COUNT(CASE WHEN vegetable = 'turnip' THEN 1 END) OVER (ORDER BY P_DATE) AS TURNIP_CNT
 25  FROM (SELECT DISTINCT custid, TRUNC(p_date,'MON') P_DATE, vegetable FROM YOUR_TABLE) T
 26     )
 27   GROUP BY P_DATE
 28   ORDER BY P_DATE;

P_DATE                TOMATO_CT CUM_TOMATO_CT  POTATO_CT CUM_POTATO_CT  TURNIP_CT CUM_TURNIP_CT
-------------------- ---------- ------------- ---------- ------------- ---------- -------------
01-JUL-2018 00:00:00          0             0          3             3          2             2
01-APR-2019 00:00:00          1             1          0             3          0             2
01-MAR-2020 00:00:00          0             1          1             4          0             2
01-APR-2020 00:00:00          1             2          0             4          0             2
01-JUN-2020 00:00:00          0             2          0             4          1             3
01-AUG-2020 00:00:00          0             2          1             5          0             3

6 rows selected.

SQL>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM