如何使用具有相同值的 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 函数按列返回正确的总和?的主要内容,如果未能解决你的问题,请参考以下文章

在 OVER 子句中使用 ORDER BY

优化 sum() over(order by...) 子句抛出“超出资源”错误

如何在MySql中返回具有相同列值的行

使用日期数据的 Over 子句分组依据

如何将相同的多窗口函数组合为一个,并在查询中的任何需要的位置调用别名?

如何选择具有多个选择值的数据作为 where 子句? - Ajax Codeigniter