在oracle中获取每个月的累计总和sql
Get a cumulative sum for each month in oracle sql
你好,我有一个有 3 列的 table。
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
如果你想要以蔬菜为中心的每月计数和累计计数,你可以这样做:
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 vegetable,在他们最早出现时,那么我会推荐两个级别的聚合:
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')
您可以使用 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>
你好,我有一个有 3 列的 table。
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
如果你想要以蔬菜为中心的每月计数和累计计数,你可以这样做:
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 vegetable,在他们最早出现时,那么我会推荐两个级别的聚合:
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')
您可以使用 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>