How do I achieve addition of each rows in T-SQL? - sql-server

I have my data which may be around 50 records for each address:
Id AddressId Income Expense Revenue
----------------------------------------
1 1 100 200 300
2 1 150 20 200
3 1 160 80 800
4 1 50 90 200
5 1 600 700 500
Now I need my data in the following format:
Ids Count Income Expense Revenue
---------------------------------------
1 1 100 200 300
1,2 2 250 220 500
1,2,3 3 410 300 1300
1,2,3,4 4 460 390 1500
1,2,3,4,5 5 1060 1090 2000
Every row is being added one after another.
For example:
The Ids 1,2 is a sum of Id 1 and 2
The Ids 1,2,3 is a sum of Id 1 and 2 and 3 and so on
I don't need the Ids column, the only thing I need is the sum

You could use STUFF, ROW_NUMBER() OVER(), and SUM() OVER() like this
DECLARE #SampleData AS TABLE
(
Id int,
AddressId int,
Income int,
Expense int,
Revenue int
)
INSERT INTO #SampleData
VALUES
( 1, 1, 100, 200, 300),
( 2, 1, 150, 20 , 200),
( 3, 1, 160, 80 , 800),
( 4, 1, 50 , 90 , 200),
( 5, 1, 600, 700, 500)
SELECT
STUFF(
(
SELECT ',' + CAST(sd1.Id AS varchar(10))
FROM #SampleData sd1
WHERE sd1.AddressId = sd.AddressId AND sd1.Id <= sd.Id
FOR XML PATH('')
),
1,1,'') AS Ids,
Row_number() OVER(PARTITION BY sd.AddressId ORDER BY sd.Id) AS Count,
sum(sd.Income) OVER(PARTITION BY sd.AddressId ORDER BY sd.Id) AS Income,
sum(sd.Expense) OVER(PARTITION BY sd.AddressId ORDER BY sd.Id) AS Expense,
sum(sd.Revenue) OVER(PARTITION BY sd.AddressId ORDER BY sd.Id) AS Revenue
FROM #SampleData sd
ORDER BY sd.AddressId, sd.Id
Demo link: http://rextester.com/HRIWH92029
Note: The last revenue should be 2000 instead of 1600

If you're using SQL server 2012 and above,
please use below query for the sum up the previous rows
Select ID,
count(*) OVER (PARTITION by AddressID
ORDER BY ID
ROWS BETWEEN unbounded PRECEDING AND current row) as[Count],
sum(Income) OVER (PARTITION by AddressID
ORDER BY ID
ROWS BETWEEN unbounded PRECEDING AND current row) Income,
sum(Expense) OVER (PARTITION by AddressID
ORDER BY ID
ROWS BETWEEN unbounded PRECEDING AND current row)Expense,
sum(Revenue) OVER (PARTITION by AddressID
ORDER BY ID
ROWS BETWEEN unbounded PRECEDING AND current row) Revenue from TableName

If you're using SQL server 2008 and below, please use below query for the sum up the previous rows.
Select ID, (select count(*) from Tablename A where A.Id<=Tablename.ID)[Count],
(select sum(Income) from Tablename A where A.Id<=Tablename.ID) Income, (select
sum(Expense) from Tablename A where A.Id<=Tablename.ID) Expense, (select
sum(Revenue) from Tablename A where A.Id<=Tablename.ID) Revenue from Tablename

Related

How to Sum the Total salary column by adding the Salary Column

Cola
Salary
TotalSalary
A
100
100
B
200
300
C
300
600
You can use the sum() window function to get a running total:
select Cola,
Salary,
Sum(Salary) over(order by Cola rows unbounded preceding) as TotalSalary
from yourtable;
Fiddle

Convert query from SQL Server to SQLite

I want to get data from 2 tables ordering them by date: to get the cumulative balance for the customer.
The 2 tables that I want to get data from are my tables: transfers & trans_payments I had done this using an SQL server and here is the query:
SELECT TOP 1000000
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) num_col,
ID, cust_id, final, value, date,
SUM(balance) OVER (PARTITION BY cust_id
ORDER BY date, seq, ID) balance,
note
FROM
(SELECT
ID, cust_id, final, 0, final balance, date, note, 0
FROM
transfers
UNION ALL
SELECT
ID, cust_id, 0, value, - value, date, note, 1
FROM
trans_payments) t (ID, cust_id, final, value, balance, date, note, seq)
ORDER BY
cust_id, date, seq
But I want to convert this query to use it in SQLite and here what I did until now :
SELECT ROW_NUMBER() OVER (ORDER BY
(SELECT 1)) num_col, ID, cust_id, final, value, date, sum(balance) OVER
(partition BY cust_id
ORDER BY date, seq, ID) balance, note
FROM (SELECT ID, cust_id, final, 0, final balance, date, note, 0
FROM transfers UNION ALL
SELECT ID, cust_id, 0, value, - value, date, note, 1
FROM trans_payments) t (ID, cust_id, final, value, balance, date, note, seq)
ORDER BY cust_id, date, seq
but I'm getting this error:near "near "(": syntax error
transfers:
ID int
cust_id int
tfrom nvarchar(200)
tto nvarchar(200)
price decimal(18, 2)
tax decimal(18, 2)
final Calculated
tnumber nvarchar(30)
note nvarchar(MAX)
date date
trans_payments:
ID int
cust_id int
value decimal(18, 2)
method nvarchar(30)
note nvarchar(MAX)
date date
Let's assume I have this data:
transfers:
ID cust_id final date
1 5 3000 22-09-2020
2 5 1500 25-09-2020
3 10 4000 28-09-2020
trans_payments:
ID cust_id value date
1 5 1000 22-09-2020
2 5 1500 23-09-2020
3 5 1000 01-10-2020
4 10 1000 28-09-2020
5 10 2000 01-10-2020
I want to create a view to show customers action on Purchases and Payments like this:
Customer 5:
cust_id final value Balance date
5 3000 0 3000 22-09-2020 --- > Purchases
5 0 1000 2000 22-09-2020 --- > payment
5 0 1500 500 23-09-2020 --- > payment
5 1500 0 2000 25-09-2020 --- > P
5 0 1000 1000 23-09-2020 --- > payment purchases
Here
In SQLite you should set the column aliases of a subquery inside the subquery.
Also, use LIMIT after the ORDER BY clause instead of TOP:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) num_col,
ID, cust_id, final, value, date,
SUM(balance) OVER (PARTITION BY cust_id ORDER BY date, seq, ID) balance,
note
FROM (
SELECT ID, cust_id, final, 0 value, final balance, date, note, 0 seq
FROM transfers
UNION ALL
SELECT ID, cust_id, 0, value, - value, date, note, 1
FROM trans_payments
)
ORDER BY cust_id, date, seq
LIMIT 1000000
See the demo.

select max value in each 5 rows

My total rows are variable and not fixed , So there are N rows and I want to separate each 5 rows as a group and select the max value of price in following table in SQL.
Date Price
20170101 100
20170102 110
20170103 90
20170105 80
20170109 76
20170110 50
20170111 55
20170113 80
20170115 100
20170120 99
20170121 88
20170122 98
20170123 120
So in first 5 group the max price is 110 , and second group is 100, and last group max price is 120.
Use a common table expression to group them.
WITH CTE AS (SELECT RANK() OVER (ORDER BY Date) AS Rank, Price
FROM yourtable)
SELECT (Rank - 1) / 5 AS GroupedDate, MAX(Price) AS MAXPRICE
FROM CTE
GROUP BY ((Rank - 1) / 5);
Output
GroupedDate MAXPRICE
0 110
1 100
2 120
SQL Fiddle: http://sqlfiddle.com/#!6/b5857/3/0
You can use row_number as below
;With cte as (
Select *, Bucket = Sum(RowN) over(Order by [date]) from (
Select *, RowN = case when row_number() over(order by [date]) % 5 = 0 then 1 else 0 end from #data1
) a
) Select top (1) with ties [Date], [Price]
from cte
order by row_number() over (partition by Bucket order by Price desc)
You could use:
SELECT grp, MAX(Price) AS price
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY DATE) / 5 AS grp FROM tab) sub
GROUP BY grp;
-- OUTPUT
grp price
0 110
1 100
2 120
Rextester Demo
*assuming that date is unique
EDIT:
As in something like : 20170101 - 20170109 110
SELECT
CONVERT(VARCHAR(8),MIN(DATE),112) + '-' + CONVERT(VARCHAR(8),MAX(date),112)
, MAX(Price) AS price
FROM (SELECT *, (ROW_NUMBER() OVER(ORDER BY DATE) ) / 5 AS grp FROM tab) sub
GROUP BY grp;
Output:
20170101-20170105 110
20170109-20170115 100
20170120-20170123 120
Rextester Demo2

sequence Rank in query

I would like to get sequence number in mssql. Please see below.
There is a table.
UserID Score TeamID
------------------------------
1 100 1
2 200 1
3 500 2
4 600 2
5 700 2
6 1000 3
I would like to sort by total score group by team. see below
RankID UserID Score TeamID TotalScore
-----------------------------------------------------------
1 3 500 2 1800
1 4 600 2 1800
1 5 700 2 1800
2 6 1000 3 1000
3 1 100 1 300
3 2 200 1 300
I want to code only one sql query. Help me someone how can I do this? Thanks.
This should work:
;WITH TotalScore AS (
SELECT UserID, Score, TeamID,
SUM(Score) OVER (PARTITION BY TeamID) AS TotalScore
FROM mytable
)
SELECT DENSE_RANK() OVER (ORDER BY TotalScore DESC) AS RankID,
UserID, Score, TeamID, TotalScore
FROM TotalScore
ORDER BY TotalScore DESC, Score
The Common Table Expression used calculates the total score per TeamID using windowed version of SUM. Using DENSE_RANK together with this calculated field we can easily generate the required RankID.
You can try this
SELECT
RANK() OVER(ORDER BY i.TotalScore DESC) AS RankID
,A.*
FROM
(
SELECT
UserID
,Score
,TeamID
,(SELECT SUM(Score) FROM yourTable tb2 WHERE tb2.TeamID = tb1.TeamID) AS TotalScore
FROM yourTable tb1
) A
ORDER BY A.TotalScore DESC
Have a Try with below,
Select DENSE_RANK() over(Order by (Select Sum(Score) from #tablename V where V.TeamID=T.TeamID ) desc )RankID
,*,
Sum(Score) over(Partition by TeamID) TotalScore from #tablename T
order by DENSE_RANK() over(Order by (Select Sum(Score) from #tablename V where V.TeamID=T.TeamID ) desc )
Dense Rank in the 'Order by' to sort the results by RANK Id and the same is used in Select statement, Subquery in the Dense Rank will rank based on the sum(Score) for a TeamID

Using "WITH OVER" statement - How to start new sequence number when another group of records are started?

Using WITH OVER or by using other method, how to start new sequence number for another group of records?
It is SQL Server 2005.
E.g. how to get following ouput (I am talking about RowNum column in expected output)?
Table:
id name
100 A
200 B
300 C
200 B
200 B
Expected ouput:
RowNum id
1 100
1 200
2 200
3 200
1 300
You're looking for PARTITION BY, Test this out.
Create table #test
(
i int
)
INSERT INTO #test
SELECT 100 UNION ALL
SELECT 200 UNION ALL
SELECT 300 UNION ALL
SELECT 200 UNION ALL
SELECT 200
SELECT I, ROW_NUMBER() OVER (PARTITION BY I ORDER BY i ASC) FROM #test
ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...)
Your example has no clear ORDER BY nor PARTITION BY the expected output. Both could be either id, either name. A better example would be:
Table:
id type
1 100
2 200
3 300
4 200
5 200
Expected:
rn id type
1 1 100
1 2 200
2 4 200
3 5 200
1 3 300
which would correspond to ROW_NUMBER() OVER (PARTITION BY type ORDER BY id)
declare #MyTable table (
id int,
name char(1)
)
insert into #MyTable
(id, name)
values
(100,'A')
insert into #MyTable
(id, name)
values
(200,'B ')
insert into #MyTable
(id, name)
values
(300,'C')
insert into #MyTable
(id, name)
values
(200,'B')
insert into #MyTable
(id, name)
values
(200,'B')
select id, row_number() over(partition by id order by id) as RowNum
from #MyTable

Resources