简体   繁体   中英

How can i use SUM function with OVER clause having same values in order by column to return correct sum?

I have a scenario where I need to get the sum column using sql SUM function. I have a sample data like this:

Sample table:

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

I'm using the query shown below to get sum over myCol column

select 
    dateCol, myCol,
    sum(case when dateCol is not null  then 1 end) over (order by dateCol) as sumCol
from   
    sampleTable;

I get these results:

    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

but I expect these results:

    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

How can I modify the query to return the expected result?

The default in SQL for cumulative sums is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW , not ROWS BETWEEN UNBOUNDED PRECEDING . You seem to have no way to distinguish the rows.

You can try an explicit window specification:

select dateCol, myCol,
       count(dateCol) over (order by dateCol rows between unbounded preceding and current row) as sumCol
from sampleTable;

Notice that I also simplified the logic, using count() instead of sum() .

If you have a column to specify the ordering, then use that column in the order by :

select dateCol, myCol,
       count(dateCol) over (order by dateCol, ?) as sumCol
from sampleTable;

That will make the sort stable and distinguish the rows.

Absent that, you can create a column. But, the results may be in a different order -- SQL tables represent unordered sets. So:

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;

I will try to explain using standard SQL. You are trying to group dateCol, myCol with agregate function sum. Basically you need to define GROUP BY clause, and result view can be sorted using ordinary order by clause

  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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM