Home > Mobile >  Subtracting a value from the current entry based on the previous column entry using LAG in MSSQL is
Subtracting a value from the current entry based on the previous column entry using LAG in MSSQL is

Time:01-05

I am trying to resolve the closing_stock_quantity column in a table where there are 0 values that should actually be the difference of the previous closing_stock_quantity and the quantity_sold for the current date (where the 0 value is). I.e the quantity sold for the day is subtracted from the previous quantity_closing_stock entry, to get the quantity_closing_stock for the day.

Note: There is no logic for getting the quantity_closing_stock, it is just data that has been retrieved.

With what I have tried so far, I am retrieving NULL values in place of these entries I am trying to calculate.

Here is an initial sample data:

unit_id timestamp quantity quantity_closing_stock
1 2022-01-01 0 100
1 2022-01-02 1 99
1 2022-01-03 3 96
1 2022-01-04 6 90
1 2022-01-05 1 0
1 2022-01-06 2 100
1 2022-01-07 5 95

I have tried to use the LAG function to resolve this, however I am receiving NULL values for those entries.

The expected output should be:

unit_id timestamp quantity quantity_closing_stock
1 2022-01-01 0 100
1 2022-01-02 1 99
1 2022-01-03 3 96
1 2022-01-04 6 90
1 2022-01-05 1 89
1 2022-01-06 2 100
1 2022-01-07 5 95

Here is the code I have tried:

WITH mycte ([timestamp],quantity_closing_stock)  AS (
    SELECT [timestamp],
        LAG(quantity_closing_stock) OVER (ORDER BY timestamp)
    FROM #my_table
    WHERE quantity_closing_stock = 0

)
    UPDATE #my_table
    SET quantity_closing_stock = mycte.quantity_closing_stock - quantity
    FROM #my_table AS id
     JOIN mycte ON mycte.[timestamp] = id.[timestamp]
        
SELECT * FROM  #my_table ORDER BY timestamp ASC

CodePudding user response:

The LAG() on the first row will return NULL because there is no previous row because your "mycte" select only the row "WHERE quantity_closing_stock = 0", you have to move the "WHERE quantity_closing_stock = 0" out of the calculation of the LAG().

CodePudding user response:

Try the following:

/* define groups using a running conditional sum window function,
   this will group quantity_closing_stock values together til a 0 value is found
*/
WITH create_groups AS
(
  SELECT *,
    SUM(CASE WHEN quantity_closing_stock=0 THEN 1 ELSE 0 END) OVER (PARTITION BY unit_id ORDER BY timestamp DESC) AS grp
  FROM table_name
),
CTE AS
(
  SELECT *,
   MAX(quantity_closing_stock) OVER (PARTITION BY unit_id, grp) - 
   SUM(quantity) OVER (PARTITION BY unit_id, grp) AS val
  FROM create_groups
)
UPDATE CTE
SET quantity_closing_stock = val
WHERE quantity_closing_stock = 0;

See demo

  • Related