Calculating the sum of running total colum - sql

I am getting running total of particular column, but now I need to get the sum of running total column
id somedate somevalue runningtotal sumofrunning total
-- -------- --------- ------------ ------------------
45 01/Jan/09 3 3 138
23 08/Jan/09 5 8 138
12 02/Feb/09 0 8 138
77 14/Feb/09 7 15 138
39 20/Feb/09 34 49 138
33 02/Mar/09 6 55 138

Please try:
select
*,
SUM(RunningTotal) OVER() SumOfRunningTotal
from
YourTable

Store the result from your query in a temp table.
select ....
into # T
from ...
Calculate the sum value to a variable.
declare #sum bigint;
select sum(runningtotal)
from #T;
And finally do the query against the temp table.
select *, #sum as [sumofrunning total]
from #T
Another way would be to do a derived table of your existing query and use sum() over() in the main query.
select T.*, sum(T.runningtotal) over() as [sumofrunning total]
from (
-- your query goes here
select ...
from ...
)

Try this (UGLY and SLOW), but seems working,
WITH somecte (id, somedate, somevalue, runningtotal, somegroupe )
AS
(
SELECT
a.id,
a.somedate,
a.somevalue,
-- Here goes your running total logic
(SELECT SUM(b.somevalue)
FROM sometable b
WHERE b.somedate <= a.somedate) AS runningtotal,
1 as somegroupe
FROM sometable a
)
SELECT id, somedate, somevalue, runningtotal,
(SELECT SUM(runningtotal)
FROM somecte
GROUP BY somegroupe) AS sumofrunningtotal
FROM somecte
Check SQLFiddle

Related

duplicate values in DB2

I am working on DB2.
There are duplicate rows in the table. I need to extract data where there is different value in 2nd column for same value in 1st column.
there are column other than these in table but only need to consider these.
for example:
NBR
SE_NBR
123
56
123
56
123
56
248
75
248
75
To extract
NBR
SE_NBR
456
12
456
34
456
11
135
77
135
88
here is one way using window function:
select * from
(
select *, min(SE_NBR) over (partition by NBR) minnbr, max(SE_NBR) over (partition by NBR) maxnbr
from nbrtable
) t
where minnbr <> maxnbr
if window function is not supported:
select * from tableName t1
where exists (
select 1 from tablename t2
where t1.NBR = t2.NBR
group by t2.nbr
having count(distinct SE_NBR) > 1
)
db<>fiddle here
You can do:
select *
from t
where nbr in (
select nbr from t group by nbr having count(distinct se_nbr) > 1
)

How to use this in sql -- > max(sum (paid * quantity )) to solve a query

How to get the max value order of each customer ?
select num, max(sum(paid*quantity))
from orders join
pizza
using (order#)
group by customer#;
table
num orderN price
-------- --- -------
1 109 30
1 118 25
3 101 30
3 115 27
4 107 23
5 100 17
5 129 16
output req-
num Pnum price
-------- --- -------
1 109 30
3 101 30
4 107 23
5 100 17
You want to select the record having the highest price in each group of nums.
If your RDBMS supports window functions, that's straight forward with ROW_NUMBER() :
SELECT num, pnum, price
FROM (
SELECT t.*, ROW_NUMBER OVER(PARTITION BY num ORDER BY price DESC) rn
FROM mytable t
) x
WHERE rn = 1
Else, you can take the following approach, that uses a NOT EXISTS condition with a correlated subquery to ensure that the record being joined in the one with the highest price for the current num :
SELECT num, pnum, price
FROM mytable t
WHERE NOT EXISTS (
SELECT 1 FROM mytable t1 WHERE t1.num = t.num AND t1.price > t.price
)

T-SQL: Row_number() group by

I am using SQL Server 2008 R2 and have a structure as below:
create table #temp( deptid int, regionid int)
insert into #temp
select 15000, 50
union
select 15100, 51
union
select 15200, 50
union
select 15300, 52
union
select 15400, 50
union
select 15500, 51
union
select 15600, 52
select deptid, regionid, RANK() OVER(PARTITION BY regionid ORDER BY deptid) AS 'RANK',
ROW_NUMBER() OVER(PARTITION BY regionid ORDER BY deptid) AS 'ROW_NUMBER',
DENSE_RANK() OVER(PARTITION BY regionid ORDER BY deptid) AS 'DENSE_RANK'
from #temp
drop table #temp
And output currently is as below:
deptid regionid RANK ROW_NUMBER DENSE_RANK
--------------------------------------------------
15000 50 1 1 1
15200 50 2 2 2
15400 50 3 3 3
15100 51 1 1 1
15500 51 2 2 2
15300 52 1 1 1
15600 52 2 2 2
My requirement however is to row_number over regionid column but by grouping and not row by row. To explain better, below is my desired result set.
deptid regionid RN
-----------------------
15000 50 1
15200 50 1
15400 50 1
15100 51 2
15500 51 2
15300 52 3
15600 52 3
Please let me know if my question is unclear. Thanks.
Use dense_rank() over (order by regionid) to get the expected result.
select deptid, regionid,
DENSE_RANK() OVER( ORDER BY regionid) AS 'DENSE_RANK'
from #temp
Partitioning within a rank/row_number window function will assign numbers within the partitions, so you don't need to use a partition on regionid to order the regionids themselves.

SUM not showing expected value in SQL

I have a table as
ID TOTAL SUM(TOTAL)
1 62 62
1 53 53
2 62 62
2 47 47
I thought the SUM(TOTAL) should look like
ID TOTAL SUM(TOTAL)
1 62 115
1 53 115
2 62 109
2 47 109
This is the query I used
select ID, TOTAL, SUM(TOTAL)
from tablename
GROUP BY TOTAL, ID
You could do a windowed SUM instead:
Select ID, TOTAL, SUM(TOTAL) OVER(PARTITION BY ID)
From tablename
This will give you the results you expected. It will display the ID and TOTAL for each row, along with the SUM of the ID grouping.
A GROUP BY is not necessary for this type of summation.
You'll need to remove the TOTAL column from the group by, and therefore the select list. Because TOTAL is in your select list and group by it can't properly aggregate how you're expecting.
SELECT ID, SUM(TOTAL)
FROM tablename
GROUP BY ID
To get your exact output:
SELECT tablename.ID,
TOTAL,
TOTALSUM
FROM (SELECT ID,
SUM(TOTAL) AS TOTALSUM
FROM tablename
GROUP BY ID) AS t
INNER JOIN
tablename
ON tablename.ID = t.ID;

Accumulate a summarized column

I could need some help with a SQL statement. So I have the table "cont" which looks like that:
cont_id name weight
----------- ---------- -----------
1 1 10
2 1 20
3 2 40
4 2 15
5 2 20
6 3 15
7 3 40
8 4 60
9 5 10
10 6 5
I then summed up the weight column and grouped it by the name:
name wsum
---------- -----------
2 75
4 60
3 55
1 30
5 10
6 5
And the result should have a accumulated column and should look like that:
name wsum acc_wsum
---------- ----------- ------------
2 75 75
4 60 135
3 55 190
1 30 220
5 10 230
6 5 235
But I didn't manage to get the last statement working..
edit: this Statement did it (thanks Gordon)
select t.*,
(select sum(wsum) from (select name, SUM(weight) wsum
from cont
group by name)
t2 where t2.wsum > t.wsum or (t2.wsum = t.wsum and t2.name <= t.name)) as acc_wsum
from (select name, SUM(weight) wsum
from cont
group by name) t
order by wsum desc
So, the best way to do this is using cumulative sum:
select t.*,
sum(wsum) over (order by wsum desc) as acc_wsum
from (<your summarized query>) t
The order by clause makes this cumulative.
If you don't have that capability (in SQL Server 2012 and Oracle), a correlated subquery is an easy way to do it, assuming the summed weights are distinct values:
select t.*,
(select sum(wsum) from (<your summarized query>) t2 where t2.wsum >= t.wsum) as acc_wsum
from (<your summarized query>) t
This should work in all dialects of SQL. To work with situations where the accumulated weights might have duplicates:
select t.*,
(select sum(wsum) from (<your summarized query>) t2 where t2.wsum > t.wsum or (t2.wsum = t.wsum and t2.name <= t.name) as acc_wsum
from (<your summarized query>) t
try this
;WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(ORDER BY wsum) rownum
FROM #table1
)
SELECT
c1.name,
c1.wsum,
acc_wsum= (SELECT SUM(c2.wsum)
FROM cte c2
WHERE c2.rownum <= c1.rownum)
FROM CTE c1;
or you can join instead of using subquery
;WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(ORDER BY usercount) rownum
FROM #table1
)
SELECT
c1.name,
c1.wsum,
acc_wsum= SUM(c2.wsum)
FROM CTE c1
INNER JOIN CTE c2 ON c2.rownum <= c1.rownum
GROUP BY c1.name, c1.wsum;