How do i do running totals from second column

半城伤御伤魂 提交于 2019-12-22 12:39:25

问题


I have a data set like below,

Lot Size    Reported QTY    Qty Balance
150          100            
150          100            
150          80             
150          80            
150          5              

The Qty Balance needs to calculated as follows,

Row 1 = Lot Size - Reported Qty (row1) => 150-100 = 50
Row 2 = Reported Qty (row1) - Reported Qty(row2) => 100-100 =0
Row 3 = Reported Qty (row2) - Reported Qty(row3) => 100-80 =20
... till the last row

My expected result is

Lot Size    Reported QTY    Qty Balance
150          100            50
150          100            0
150          80             20
150          80             0
150          5              75

How do I achieve this in a query?


回答1:


SQL Fiddle

Oracle 11g R2 Schema Setup:

CREATE TABLE lots ( Lot_Size, Reported_QTY ) AS
          SELECT 150, 100 FROM DUAL
UNION ALL SELECT 150, 100 FROM DUAL
UNION ALL SELECT 150,  80 FROM DUAL
UNION ALL SELECT 150,  80 FROM DUAL
UNION ALL SELECT 150,   5 FROM DUAL;

Query 1:

SELECT Lot_Size,
       Reported_QTY,
       COALESCE( LAG( Reported_QTY ) OVER ( ORDER BY NULL ) - Reported_QTY,
                 Lot_Size - Reported_QTY ) AS Qty_Balance
FROM   Lots

Results:

| LOT_SIZE | REPORTED_QTY | QTY_BALANCE |
|----------|--------------|-------------|
|      150 |          100 |          50 |
|      150 |          100 |           0 |
|      150 |           80 |          20 |
|      150 |           80 |           0 |
|      150 |            5 |          75 |



回答2:


You should take a look at the LAG() analytic function. See here for details on the function and the parameters it accepts (for example, I think you're going to need to pass in a default of the lot_size column for when the lag() function returns null.)

Once you've identified the previous row's reported qty value, then you can simply subtract it. You will, of course, need some way of identifying the order of the rows - your sample data doesn't appear to have one, so the database won't be able to determine which row is first and which is last.

Eg.

with sample_data (lot_size, reported_qty) as (SELECT 150, 100 FROM DUAL
                                              UNION ALL SELECT 150, 100 FROM DUAL
                                              UNION ALL SELECT 150,  80 FROM DUAL
                                              UNION ALL SELECT 150,  80 FROM DUAL
                                              UNION ALL SELECT 150,   5 FROM DUAL)
select lot_size,
       reported_qty,
       lag(reported_qty, 1, lot_size) over (order by null) - reported_qty diff
from   sample_data;

  LOT_SIZE REPORTED_QTY       DIFF
---------- ------------ ----------
       150          100         50
       150          100          0
       150           80         20
       150           80          0
       150            5         75



回答3:


As @Boneist suggested, you need to use LAG() OVER() analytic function.

You just need to do one more task to handle the first row which will be NULL, using CASE you could make it work.

Test case

SQL> WITH data AS
  2    ( SELECT t.*, lag(reported_qty) OVER(ORDER BY NULL) rn FROM t
  3    )
  4  SELECT lot_size,
  5    reported_qty,
  6    CASE
  7      WHEN rn IS NULL
  8      THEN lot_size     - reported_qty
  9      ELSE rn - reported_qty
 10    END qty_balance
 11  FROM data;

  LOT_SIZE REPORTED_QTY QTY_BALANCE
---------- ------------ -----------
       150          100          50
       150          100           0
       150           80          20
       150           80           0
       150            5          75

SQL>


来源:https://stackoverflow.com/questions/30374885/how-do-i-do-running-totals-from-second-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!