SQL-缺少group by值时的累计总和
作为我上一张罚单的后续——我现在认为这个例子太简单了,我准备了一个场景的例子,在这个场景中,我希望在date_col列上聚合列cus_sum group,并在代表唯一客户号的cus列上聚合列cus_sum group。 我希望生成一系列日期,例如从2018年1月1日到2018年1月10日的函数生成序列,然后为每个客户生成一个累积的cus_sum列。在下面的例子中,您可以想象,有些日子完全没有信息,有些日子并非所有客户都有任何记录——不管我想显示他们在这段时间内的累计金额SQL-缺少group by值时的累计总和,sql,postgresql,cumulative-sum,Sql,Postgresql,Cumulative Sum,作为我上一张罚单的后续——我现在认为这个例子太简单了,我准备了一个场景的例子,在这个场景中,我希望在date_col列上聚合列cus_sum group,并在代表唯一客户号的cus列上聚合列cus_sum group。 我希望生成一系列日期,例如从2018年1月1日到2018年1月10日的函数生成序列,然后为每个客户生成一个累积的cus_sum列。在下面的例子中,您可以想象,有些日子完全没有信息,有些日子并非所有客户都有任何记录——不管我想显示他们在这段时间内的累计金额 CREATE TABLE
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],产品购买产品数量-这是我希望为每个客户和系列中的每一天累积的总和。假设您有单独的客户表,因此,您可以使用CTE生成数据范围,然后连接croos join customer表,以获得客户和日期的所有组合,然后从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
假设您有单独的客户表,那么您可以使用CTE生成数据范围,然后加入croos join customer table以获得客户和日期的所有组合,然后从test2 table获得总和。查询如下所示-
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
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的预期结果有错误
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的预期结果有错误
将上面的查询调整为我的表,但输出不符合预期。generate series函数未按预期和定义创建日时间框架-因此缺少日。我正在调查的另一个问题是如何推断所有客户,而不仅仅是数组中定义的客户-列出所有客户是无效的。Ad 1。当然,generate_系列做了答案中所示的事情。如果你有问题,在广告2中展示给他们看。您可以从test2中选择不同的CU,而不是unnestarray[1,2]——请参阅更新的答案。让它工作起来了——对该查询如何实现进行了更多的调查。不过,感谢一个与lota相关的问题-从优化的角度来看,从数据库中的最小查找日期到今天生成一个系列并并行查找每个客户的第一个购买日期是否有意义-并从那里开始计算每个客户的累计金额。或者反过来,从所有客户的第一次购买开始生成一个系列。第一个选项可能会导致过于复杂的查询。我敢打赌简单性,也就是说,为所有客户生成一个公共系列,并可能选择性地删除每个客户的初始行,使其成为第一个非零值。这两个变量之间的性能差异应该不大。将上面的查询调整为我的表,但输出不符合预期。generate series函数未按预期和定义创建日时间框架-因此缺少日。我正在调查的另一个问题是如何推断所有客户,而不仅仅是数组中定义的客户-列出所有客户是无效的。Ad 1。当然,generate_系列做了答案中所示的事情。如果你有问题,在广告2中展示给他们看。您可以从test2中选择不同的CU,而不是unnestarray[1,2]——请参阅更新的答案。让它工作起来了——对该查询如何实现进行了更多的调查。不过,感谢一个与lota相关的问题-从优化的角度来看,从数据库中的最小查找日期到今天生成一个系列并并行查找每个客户的第一个购买日期是否有意义-并从那里开始计算每个客户的累计金额。或者反过来,从所有客户的第一次购买开始生成一个系列。第一个选项可能会导致过于复杂的查询。我敢打赌简单性,也就是说,为所有客户生成一个公共系列,并可能选择性地删除每个客户的初始行,使其成为第一个非零值。这两个变体之间的性能差异不应该很大。是否可以将其应用于PostgreSQL?它应该可以工作,您是否遇到任何异常?我对PostageSQL不太熟悉,但这是一个通用的SQL查询,应该可以使用。是否可以将其应用于PostgreSQL?应该可以,您是否遇到任何异常?我对PostageSQL不太熟悉,但这是通用的SQL查询,应该可以工作。