【问题标题】:Get a cumulative sum for each month in oracle sql在oracle sql中获取每个月的累计总和
【发布时间】:2021-03-16 08:59:56
【问题描述】:

您好,我有一个包含 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

我需要根据蔬菜计算客户的不同计数 列以及每个月的累积总和

输出应该有下面的列

date        
tomato_ct 
cum_tomato_ct
potato_ct
cum_potato_ct
turnip_ct        
cum_turnip_ct

【问题讨论】:

  • 请向我们展示您想要的结果,而不仅仅是列名。

标签: sql oracle datetime count distinct


【解决方案1】:

如果您想要以蔬菜为中心的每月计数和累积计数,您可以这样做:

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')

您提到您想要统计不同个客户。如果您只想在他们最早出现的时候统计每个客户一次par蔬菜,那么我会推荐两个级别的聚合:

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')

【讨论】:

  • 我得到了我想要的输出。谢谢你。验证计数
  • 我不同意!!!这将引发错误,因为聚合函数中不允许使用分析函数。
  • @Popeye: 反过来说:聚合函数在解析函数内部。
  • 在同一个查询中,如果我需要总客户数和累计数,我如何编辑shd?
【解决方案2】:

您可以使用analytical 函数和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>

【讨论】:

  • 你能解释一下上面的查询吗? max(tomato_cnt) 如何给出累计和?
  • 因为内部查询对所有提到的蔬菜都有累积计算。并且通过使用 MAX,它使用分组月份的所有累积计数的最大值。如果您将单独执行内部查询,那么您将能够在外部查询中看到 MAX 背后的逻辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多