26

I can't understand this code's bug

ID      AccountID       Quantity
1          1               10           Sum = 10
2          1               5                = 10 + 5 = 15
3          1               2                = 10 + 5 + 2 = 17
4          2               7                = 7
5          2               3                = 7 + 3 = 10  

SELECT ID, AccountID, Quantity, 
       SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT, 
FROM tCariH
Willi Mentzel
  • 24,988
  • 16
  • 102
  • 110
serkan
  • 375
  • 1
  • 4
  • 4

3 Answers3

35

Seems like you expected the query to return running totals, but it must have given you the same values for both partitions of AccountID.

To obtain running totals with SUM() OVER (), you need to add an ORDER BY sub-clause after PARTITION BY …, like this:

SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY ID)

But remember, not all database systems support ORDER BY in the OVER clause of a window aggregate function. (For instance, SQL Server didn't support it until the latest version, SQL Server 2012.)

Andriy M
  • 73,804
  • 16
  • 91
  • 150
  • 10
    To clarify this: a sum() without an `order by` will simply sum all values for the group defined by the partition. Btw: SQL Server was/is the only (AFAIK) DBMS supporting windowing functions without supporting an order by in the partition clause. The others (PostgreSQL, Oracle, DB2, Teradata) do not have that limitation – a_horse_with_no_name Apr 06 '12 at 08:29
  • 1
    I think you must be right about the systems with limited support of windowing aggregate functions. I did suspect that but wasn't quite sure. Having a look at another (related) question of the OP's, I can now see that SQL Server *is* the OP's database system particularly in this case, and a pre-2012 one too. – Andriy M Apr 06 '12 at 08:37
  • 1
    From what I can tell, `ORDER BY` was added in Sql 2005: http://msdn.microsoft.com/en-us/library/ms189461(v=sql.100).aspx – Robert Jeppesen Apr 26 '13 at 14:21
  • 2
    @RobertJeppesen: Yes, but only for *ranking* window functions. Support for `ORDER BY` in *aggregate* window functions was only added in SQL Server 2012. (Take a look at the [SQL Server 2005 version](http://msdn.microsoft.com/en-us/library/ms189461%28v=sql.90%29.aspx) of that manual, it's a bit clearer there.) – Andriy M Apr 26 '13 at 15:35
12

if you are using SQL 2012 you should try

SELECT  ID, 
        AccountID, 
        Quantity, 
        SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY AccountID rows between unbounded preceding and current row ) AS TopBorcT, 
FROM tCariH

if available, better order by date column.

UV.
  • 472
  • 6
  • 9
8

Query would be like this:

SELECT ID, AccountID, Quantity, 
       SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT 

       FROM #Empl ORDER BY AccountID

Partition by works like group by. Here we are grouping by AccountID so sum would be corresponding to AccountID.

First first case, AccountID = 1 , then sum(quantity) = 10 + 5 + 2 => 17 & For AccountID = 2, then sum(Quantity) = 7+3 => 10

so result would appear like attached snapshot.

xan
  • 7,310
  • 8
  • 43
  • 64