SQL-缺少按值分组时的累积总和

时间:2018-07-19 17:35:35

标签: sql postgresql cumulative-sum

作为我之前的票证的后续内容-我现在认为示例太简单了(previous question),我准备了一个示例,该示例希望汇总列cus_sum date_col列和cus列上的唯一组代表唯一的客户编号。 我希望生成一系列日期(例如,函数generate series),从2018年1月1日到2018年1月10日,然后为每个客户累积cus_sum列的总和。就像下面的情况一样,您可以想象有些日子根本没有信息,有些日子并非所有客户都有任何记录-无论我想显示其在这段时间内的累计金额。

CREATE TABLE test2 (date_col date, cus int, cus_sum int);
    insert into test2 values ('2018-01-01', 1, 5);
    insert into test2 values ('2018-01-02', 1, 12);
    insert into test2 values ('2018-01-02', 2, 14);
    insert into test2 values ('2018-01-03', 2, 8);
    insert into test2 values ('2018-01-03', 2, 10);
    insert into test2 values ('2018-01-04', 1, 22);
    insert into test2 values ('2018-01-06', 2, 20);
    insert into test2 values ('2018-01-06', 1, 5);
    insert into test2 values ('2018-01-07', 1, 45);
    insert into test2 values ('2018-01-08', 2, 32);

输出应如下所示:

date_col       cus  cum_sum
"2018-01-01"    1   5
"2018-01-01"    2   0
"2018-01-02"    1   17
"2018-01-02"    2   14
"2018-01-03"    1   17
"2018-01-03"    2   32
"2018-01-04"    1   39
"2018-01-04"    2   32
"2018-01-05"    1   39
"2018-01-05"    2   32
"2018-01-06"    1   89
"2018-01-06"    2   52
"2018-01-07"    1   134
"2018-01-07"    2   52
"2018-01-08"    1   134
"2018-01-08"    1   84

也许我应该补充一点-我假设一个表将是一个虚拟表,该表在给定时间范围内生成日期列表。第二张表是客户[1,3,4,5..10]的列表,产品购买量(产品数量),这是我希望为该系列的每个客户和每一天累积的总和。

2 个答案:

答案 0 :(得分:1)

generate_series()unnest()的交叉联接将创建一个包含所有可能值的虚拟表:

select distinct
    date_col::date, 
    cus, 
    coalesce(sum(cus_sum) over (partition by cus order by date_col), 0) as cum_sum
from generate_series('2018-01-01'::date, '2018-01-08', '1d') as date_col
cross join (select distinct cus from test2) c
left join test2 using (date_col, cus)   
order by date_col, cus

  date_col  | cus | cum_sum 
------------+-----+---------
 2018-01-01 |   1 |       5
 2018-01-01 |   2 |       0
 2018-01-02 |   1 |      17
 2018-01-02 |   2 |      14
 2018-01-03 |   1 |      17
 2018-01-03 |   2 |      32
 2018-01-04 |   1 |      39
 2018-01-04 |   2 |      32
 2018-01-05 |   1 |      39
 2018-01-05 |   2 |      32
 2018-01-06 |   1 |      44
 2018-01-06 |   2 |      52
 2018-01-07 |   1 |      89
 2018-01-07 |   2 |      52
 2018-01-08 |   1 |      89
 2018-01-08 |   2 |      84
(16 rows)

OP的预期结果似乎有误。

DbFiddle.

答案 1 :(得分:0)

假设您有单独的客户表,则可以使用CTE生成数据范围,然后将croos join customer表加入到具有customer和date的所有组合的关系中,然后从test2表中获得总和。该查询将如下所示-

WITH DateRange AS (
        SELECT
         [MyDate] = CONVERT(DATETIME,'01/01/2018')
        UNION ALL 
        SELECT
         [MyDate] = DATEADD(DAY, 1, [Date])
        FROM
         DateRange
        WHERE
         [MyDate] <= '01/10/2018'
) SELECT
 d.[MyDate]
 c.cus
 (
  select isnull(sum(cus_sume),0) 
  from test2 t 
  where t.date = d.mydate 
  and c.cust = t.cust
 ) as cus_sum
FROM
 DateRange d 
 cross join customer c
order by d.MyDate