如何使用具有相同值的 OVER 子句的 SUM 函数按列返回正确的总和?
Posted
技术标签:
【中文标题】如何使用具有相同值的 OVER 子句的 SUM 函数按列返回正确的总和?【英文标题】:How can i use SUM function with OVER clause having same values in order by column to return correct sum? 【发布时间】:2019-06-27 15:05:32 【问题描述】:我有一个场景,我需要使用 sql SUM 函数获取 sum 列。我有一个这样的示例数据:
示例表:
dateCol, myCol
-----------------------
'12:00:01' 3
'12:00:01' 4
'12:00:01' 5
'12:00:01' NULL
'12:00:01' NULL
'12:00:01' 3
我正在使用下面显示的查询来获取 myCol 列的总和
select
dateCol, myCol,
sum(case when dateCol is not null then 1 end) over (order by dateCol) as sumCol
from
sampleTable;
我得到了这些结果:
dateCol myCol sumCol
--------------------------
1 12:00:01 3 4
2 12:00:01 4 4
3 12:00:01 5 4
4 12:00:01 NULL 4
5 12:00:01 NULL 4
6 12:00:01 3 4
但我希望得到这些结果:
dateCol myCol sumCol
--------------------------
1 12:00:01 3 1
2 12:00:01 4 2
3 12:00:01 5 3
4 12:00:01 NULL 3
5 12:00:01 NULL 3
6 12:00:01 3 4
如何修改查询以返回预期结果?
【问题讨论】:
由于dateCol
包含您正在显示的行的相同日期,order by dateCol
导致任意顺序。您的运行总计甚至可以采用与结果行的顺序不同的顺序(日期不同时甚至会出现这种情况,因为您的查询缺少ORDER BY
子句)。您需要额外的列进行排序或使用ROW_NUMBER
创建一列才能开始。
【参考方案1】:
SQL 中累积和的默认值为RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
,而不是ROWS BETWEEN UNBOUNDED PRECEDING
。您似乎无法区分行。
您可以尝试明确的窗口规范:
select dateCol, myCol,
count(dateCol) over (order by dateCol rows between unbounded preceding and current row) as sumCol
from sampleTable;
请注意,我还简化了逻辑,使用count()
而不是sum()
。
如果您有一个列来指定排序,那么在order by
中使用该列:
select dateCol, myCol,
count(dateCol) over (order by dateCol, ?) as sumCol
from sampleTable;
这将使排序稳定并区分行。
如果没有,您可以创建一个列。但是,结果可能有不同的顺序——SQL 表表示 无序 集。所以:
select dateCol, myCol,
count(dateCol) over (order by dateCol, seqnum) as sumCol
from (select st.*, row_number() over (order by dateCol) as seqnum
from sampleTable
) st;
【讨论】:
【参考方案2】:我将尝试使用标准 SQL 进行解释。您正在尝试使用聚合函数 sum 对 dateCol、myCol 进行分组。基本上你需要定义 GROUP BY 子句,结果视图可以使用普通的 order by 子句进行排序
select dateCol, myCol,
sum(case when dateCol is not null then 1 else 0 end) as sumCol
from sampleTable
group by dateCol, myCol
order by dateCol
【讨论】:
以上是关于如何使用具有相同值的 OVER 子句的 SUM 函数按列返回正确的总和?的主要内容,如果未能解决你的问题,请参考以下文章
优化 sum() over(order by...) 子句抛出“超出资源”错误