Reputation: 1705
I have table named #t1 and three columns. CODE, Column1, and Column2.
create table #t1 (
CODE NVARCHAR(20),
COLUMN1 NUMERIC(18,2),
COLUMN2 NUMERIC(18,2)
)
And i have some data:
INSERT INTO #t1 (CODE,COLUMN1,COLUMN2)
VALUES ('432', 0,100),
('TOTAL FOR 432',0,100),
('4320001',0,250),
('4320001',50,0),
('4320001',0,140),
('4320001',300,0),
('TOTAL FOR 4320001',350,390),
('432002',200,0),
('432002',0,100),
('TOTAL FOR 432002',200,100)
drop table #t1
I want to have 4 column (named BALANCE). Balance must be column that represent running totals between two columns (Column1 - Column2) for each group of data. For each group total must start from zero.
Output:
CODE COLUMN1 COLUMN2 BALANCE
432 0.00 100.00 -100
TOTAL 432 0.00 100.00 -100
4320001 0.00 250.00 -250
4320001 50.00 0.00 -200
4320001 0.00 140.00 -340
4320001 300.00 0.00 -40
TOTAL 4320001 350.00 390.00 -40
432002 200.00 0.00 200
432002 0.00 100.00 100
TOTAL 432002 200.00 100.00 100
After total 432 it starts to count again for total 4320001 and agian for total 432002..... How can i get this result?
I'm using MS SQL SERVER 2014
EDIT: I have tried so far this (but that is not good):
SUM(sum(column1)-sum(column2)) OVER(ORDER BY code rows UNBOUNDED PRECEDING) AS SALDO
Upvotes: 0
Views: 174
Reputation: 3342
as per your output :)
DECLARE @t1 TABLE (
CODE nvarchar(20),
COLUMN1 numeric(18, 2),
COLUMN2 numeric(18, 2)
)
INSERT INTO @t1 (CODE, COLUMN1, COLUMN2)
VALUES ('432', 0, 100),
('TOTAL FOR 432', 0, 100),
('4320001', 0, 250),
('4320001', 50, 0),
('4320001', 0, 140),
('4320001', 300, 0),
('TOTAL FOR 4320001', 350, 390),
('432002', 200, 0),
('432002', 0, 100),
('TOTAL FOR 432002', 200, 100)
-- CTE
;
WITH CTE
AS (SELECT
*,
ROW_NUMBER() OVER (ORDER BY @@rowcount) RowNum -- Order as per the input
FROM @t1)
-- get from CTE
SELECT
*,
SUM(COLUMN1 - COLUMN2) OVER (PARTITION BY code ORDER BY RowNum) AS Balance --sum using PARTITION
FROM CTE
ORDER BY RowNum
Upvotes: 2
Reputation: 72165
You can use the following query to get the expected result set:
SELECT CODE_NAME, COLUMN1, COLUMN2, BALANCE
FROM (
SELECT CODE, CODE AS CODE_NAME, 1 AS ORD, COLUMN1, COLUMN2,
SUM(COLUMN1 - COLUMN2)
OVER (PARTITION BY CODE ORDER BY id) AS BALANCE
FROM t1
UNION ALL
SELECT CODE, CONCAT ('TOTAL FOR ', CODE) AS CODE_NAME, 2 AS ORD,
SUM(COLUMN1), SUM(COLUMN2),
SUM(COLUMN1 - COLUMN2) AS BALANCE
FROM t1
GROUP BY CODE
) AS t
ORDER BY CODE, ORD
The above assumes that there is an auto-increment PK column, id
, that is used to define order. It also assumes that total aggregates are not stored in your original table.
Running totals are easily calculated using windowed version of SUM
aggregate function. PARTITION BY
in the OVER
clause results in totals being calculated per CODE
slice. ORDER BY id
in the OVER
clause is what causes running total calculation.
Total aggregates are calculated by a separate query. ORD
field helps us correctly order CODE
slices after UNION ALL
is performed.
Upvotes: 0