Question

Given the following table

PAYMENT_Date  TRANSACTION_TYPE     PAYMENT_AMT
1/1/2012      P                    184366     
1/1/2012      R                    -5841     
1/2/2012      P                    941
1/3/2012      P                    901
1/3/2012      R                    5841

and the following query:

select  payment_date, transaction_type, payment_amt,
        SUM(payment_amt) OVER(ORDER BY payment_date, transaction_type 
            RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS RUNNING_BALANCE
from    TABLE;

I get these results:

PAYMENT_Date  TRANSACTION_TYPE     PAYMENT_AMT  RUNNING_BALANCE
1/1/2012      P                    184366       0
1/1/2012      R                    -5841        -184366
1/2/2012      P                    941          -178525
1/3/2012      P                    901          -179466
1/3/2012      R                    5841         -180367

EXPECTED:

PAYMENT_Date  TRANSACTION_TYPE     PAYMENT_AMT  RUNNING_BALANCE
1/1/2012      P                    184366       0
1/1/2012      R                    -5841        184366
1/2/2012      P                    941          178525
1/3/2012      P                    901          179466
1/3/2012      R                    5841         180367

Why does RUNNING_BALANCE come back as a negative number? How can I make it not, besides the obvious abs()?

Was it helpful?

Solution

I think you need to change:

RANGE  BETWEEN   CURRENT ROW           AND   UNBOUNDED FOLLOWING`  

to:

ROWS   BETWEEN   UNBOUNDED PRECEDING   AND   1 PRECEDING

Test in SQLfiddle:

SELECT  payment_date, transaction_type, payment_amt,
        COALESCE( SUM(payment_amt) 
                  OVER( ORDER BY payment_date, transaction_type
                        ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
                , 0)  AS RUNNING_BALANCE
FROM    T;

OTHER TIPS

First, the data and query you posted don't appear to generate the output you're seeing. So there is some sort of copy and paste error somewhere

SQL> with t as (
  2    select date '2012-01-01' payment_date, 'P' transaction_type, 184366 payment_amt from dual union all
  3    select date '2012-01-01', 'R', -5841 from dual union all
  4    select date '2012-01-02', 'P', 941 from dual union all
  5    select date '2012-01-03', 'P', 901 from dual union all
  6    select date '2012-01-03', 'R', 5841 from dual
  7  )
  8  select  payment_date, transaction_type, payment_amt,
  9          SUM(payment_amt) OVER(ORDER BY payment_date, transaction_type
 10              RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS RUNNING_BALANCE
 11  from    T;

PAYMENT_D T PAYMENT_AMT RUNNING_BALANCE
--------- - ----------- ---------------
01-JAN-12 P      184366          186208
01-JAN-12 R       -5841            1842
02-JAN-12 P         941            7683
03-JAN-12 P         901            6742
03-JAN-12 R        5841            5841

Normally, a running balance would be done just by omitting the RANGE BETWEEN clause.

SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2    select date '2012-01-01' payment_date, 'P' transaction_type, 184366 payment_amt from dual union all
  3    select date '2012-01-01', 'R', -5841 from dual union all
  4    select date '2012-01-02', 'P', 941 from dual union all
  5    select date '2012-01-03', 'P', 901 from dual union all
  6    select date '2012-01-03', 'R', 5841 from dual
  7  )
  8  select  payment_date, transaction_type, payment_amt,
  9          SUM(payment_amt) OVER(ORDER BY payment_date, transaction_type) AS RUNNING_BALANCE
 10* from    T
SQL> /

PAYMENT_D T PAYMENT_AMT RUNNING_BALANCE
--------- - ----------- ---------------
01-JAN-12 P      184366          184366
01-JAN-12 R       -5841          178525
02-JAN-12 P         941          179466
03-JAN-12 P         901          180367
03-JAN-12 R        5841          186208

In your case, though, it sounds like you want the running balance to exclude the current row's payment. That's a bit odd buy you can do it by adding an additional LAG

SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2    select date '2012-01-01' payment_date, 'P' transaction_type, 184366 payment_amt from dual union all
  3    select date '2012-01-01', 'R', -5841 from dual union all
  4    select date '2012-01-02', 'P', 941 from dual union all
  5    select date '2012-01-03', 'P', 901 from dual union all
  6    select date '2012-01-03', 'R', 5841 from dual
  7  )
  8  select  payment_date,
  9          transaction_type,
 10          payment_amt,
 11          NVL( LAG(running_balance) OVER(ORDER BY payment_date,
 12                                                  transaction_type), 0) new_running_balance
 13    from (select payment_date,
 14                 transaction_type,
 15                 payment_amt,
 16                 SUM(payment_amt) OVER(ORDER BY payment_date,
 17                                                transaction_type) AS RUNNING_BALANCE
 18*           from t)
SQL> /

PAYMENT_D T PAYMENT_AMT NEW_RUNNING_BALANCE
--------- - ----------- -------------------
01-JAN-12 P      184366                   0
01-JAN-12 R       -5841              184366
02-JAN-12 P         941              178525
03-JAN-12 P         901              179466
03-JAN-12 R        5841              180367
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top