I have two tables Customers and Purchases:
Customers table:
+------------+-----------+----------+
| CustomerID | FirstName | Surname |
+------------+-----------+----------+
| 101 | Jeff | Smith |
| 102 | Alex | Jones |
| 103 | Pam | Clark |
| 104 | Zola | Lona |
| 105 | Simphele | Ndima |
| 106 | Andre | Williams |
| 107 | Wayne | Shelton |
| 108 | Bob | Banard |
| 109 | Ken | Davidson |
| 110 | Sally | Ivan |
+------------+-----------+----------+
Purchases table:
+------------+--------------+------------+-----------+
| PurchaseId | PurchaseDate | CustomerID | ProductID |
+------------+--------------+------------+-----------+
| 1 | 2012-08-15 | 105 | a510 |
| 2 | 2012-08-15 | 102 | a510 |
| 3 | 2012-08-15 | 103 | a506 |
| 4 | 2012-08-16 | 105 | a510 |
| 5 | 2012-08-17 | 106 | a507 |
| 6 | 2012-08-17 | 107 | a509 |
| 7 | 2012-08-18 | 108 | a502 |
| 8 | 2012-08-19 | 108 | a510 |
| 9 | 2012-08-19 | 109 | a502 |
| 10 | 2012-08-20 | 110 | a503 |
| 11 | 2012-08-21 | 101 | a510 |
| 12 | 2012-08-22 | 102 | a507 |
+------------+--------------+------------+-----------+
My question (which I have been struggling with for the last 2 days): create a query that will display all the customers who purchased products after five days or more, since their last purchase.
Desired outputs:
+-----------+------------------+
| Firstname | Daysdifference |
+-----------+------------------+
| Alex | 7 |
+-----------+------------------+
select c.FirstName, t.dif as Daysdifference from customer c
inner join
(
select p1.CustomerID,
datediff(day,p1.PurchaseDate,p2.PurchaseDate) as dif
from purchases p1
inner join purchases p2
on p1.CustomerID=p2.CustomerID
where datediff(day,p1.PurchaseDate,p2.PurchaseDate)>=5
) t
on t.CustomerID= c.CustomerID
Here you go:
DECLARE #Customers TABLE (CustomerID INT, FirstName VARCHAR(30), Surname VARCHAR(30));
DECLARE #Purchases TABLE (PurchaseId INT, PurchaseDate DATE, CustomerID INT, ProductID VARCHAR(10) );
/**/
INSERT INTO #Customers VALUES
(101,'Jeff ' , 'Smith '),
(102,'Alex ' , 'Jones '),
(103,'Pam ' , 'Clark '),
(104,'Zola ' , 'Lona '),
(105,'Simphele' , 'Ndima '),
(106,'Andre ' , 'Williams'),
(107,'Wayne ' , 'Shelton '),
(108,'Bob ' , 'Banard '),
(109,'Ken ' , 'Davidson'),
(110,'Sally ' , 'Ivan ');
INSERT INTO #Purchases VALUES
(1, '2012-08-15' ,105, 'a510'),
(2, '2012-08-15' ,102, 'a510'),
(3, '2012-08-15' ,103, 'a506'),
(4, '2012-08-16' ,105, 'a510'),
(5, '2012-08-17' ,106, 'a507'),
(6, '2012-08-17' ,107, 'a509'),
(7, '2012-08-18' ,108, 'a502'),
(8, '2012-08-19' ,108, 'a510'),
(9, '2012-08-19' ,109, 'a502'),
(10,'2012-08-20' ,110, 'a503'),
(11,'2012-08-21' ,101, 'a510'),
(12,'2012-08-22' ,102, 'a507');
--
WITH CTE AS (
SELECT Pur1.CustomerID, DATEDIFF(DAY, Pur1.PurchaseDate, Pur2.PurchaseDate) Daysdifference
FROM #Purchases Pur1 INNER JOIN #Purchases Pur2 ON Pur1.CustomerID = Pur2.CustomerID
)
SELECT Cus.FirstName, CTE.Daysdifference
FROM #Customers Cus INNER JOIN CTE ON Cus.CustomerID = CTE.CustomerID
WHERE CTE.Daysdifference >= 5;
Result:
+-----------+------------------+
| Firstname | Daysdifference |
+-----------+------------------+
| Alex | 7 |
+-----------+------------------+
Demo
You can solve it like this:
Create a ranking based on date desc and partitioned by customer id
Next check date diff between consecutive ranks to find those customers
Query below
; with cte as
(
select
*,
row_number() over(partition by CustomerID order by PurchaseDate desc) r
from
Purchases
)
select
Name= c.FirstName,
Daysdifference =datediff(d,c1.PurchaseDate, c2.PurchaseDate)
from
Customers c join
cte c1
on c.customerid=c1.customerid
join cte c2
on c1.CustomerID=c2.CustomerId
and c1.r-1=c2.r
and datediff(d,c1.PurchaseDate, c2.PurchaseDate) >=5
See working demo
Since SQL Server 2012 and the addition of the LAG & LEAD functions, there is no reason at all to do a self join for something like this...
Note... Ranking function can be extremely efficient compared to other methods BUT they do need the help of a proper index to perform their best (note the additional POC index in the test script).
CREATE TABLE #Customers (
CustomerID INT PRIMARY KEY,
FirstName VARCHAR(30),
Surname VARCHAR(30)
);
CREATE TABLE #Purchases (
PurchaseId INT PRIMARY KEY,
PurchaseDate DATE,
CustomerID INT,
ProductID VARCHAR(10)
);
INSERT INTO #Customers VALUES
(101,'Jeff ' , 'Smith '),
(102,'Alex ' , 'Jones '),
(103,'Pam ' , 'Clark '),
(104,'Zola ' , 'Lona '),
(105,'Simphele' , 'Ndima '),
(106,'Andre ' , 'Williams'),
(107,'Wayne ' , 'Shelton '),
(108,'Bob ' , 'Banard '),
(109,'Ken ' , 'Davidson'),
(110,'Sally ' , 'Ivan ');
INSERT INTO #Purchases VALUES
(1, '2012-08-15' ,105, 'a510'),
(2, '2012-08-15' ,102, 'a510'),
(3, '2012-08-15' ,103, 'a506'),
(4, '2012-08-16' ,105, 'a510'),
(5, '2012-08-17' ,106, 'a507'),
(6, '2012-08-17' ,107, 'a509'),
(7, '2012-08-18' ,108, 'a502'),
(8, '2012-08-19' ,108, 'a510'),
(9, '2012-08-19' ,109, 'a502'),
(10,'2012-08-20' ,110, 'a503'),
(11,'2012-08-21' ,101, 'a510'),
(12,'2012-08-22' ,102, 'a507');
-- add POC index...
CREATE NONCLUSTERED INDEX ix_POC ON #Purchases (CustomerID, PurchaseDate);
--===========================================================
SELECT
c.FirstName,
p2.Daysdifference
FROM
#Customers c
JOIN (
SELECT
p.CustomerID,
Daysdifference = DATEDIFF(DAY, p.PurchaseDate, LEAD(p.PurchaseDate, 1) OVER (PARTITION BY p.CustomerID ORDER BY p.PurchaseDate))
FROM
#Purchases p
) p2
ON c.CustomerID = p2.CustomerID
WHERE
p2.Daysdifference >= 5;
Results...
FirstName Daysdifference
------------------------------ --------------
Alex 7
Related
Course
+-----+----------+
| id | c_name |
+-----+----------+
| 1 | course1 |
| 7 | course2 |
+-----+----------+
Chapter
+-----+----------+------------+
| id | Ch_name | c_id |
+-----+----------+------------+
| 3 | Chapter1 | 1 |
| 9 | Chapter2 | 7 |
| 11 | Chapter3 | 1 |
| 17 | Chapter4 | 1 |
+-----+----------+------------+
I'm trying to select all data so that I can generate the following output:
+-----+-- |
|Course |
+-----+-- |
|Course1 |
|Chapter1 |
|Chapter3 |
|Chapter4 |
| |
|Course2 |
|Chapter2 |
I have tried in this way:
select
c.CourseID ,
'Course' as table_name,
c.CourseName as Course,
'' as Chapter
from [MstCourse]c
union
select
s.CourseID,
'Chapter' as table_name,
c.CourseName as Course,
s.ChapterName as Chapter
from [MstCourse] c
inner JOIN [ManageChapter] s ON c.CourseID= s.CourseID
order by Course, Chapter
But I am not getting the results in a single column.
You could achieve this with a group by ... with rollup clause.
Sample data
create table course
(
id int,
name nvarchar(10)
);
insert into course(id, name) values
(1, 'Course1'),
(7, 'Course2');
create table chapter
(
id int,
name nvarchar(10),
c_id int
);
insert into chapter(id, name, c_id) values
(3 , 'Chapter1', 1),
(9 , 'Chapter2', 7),
(11, 'Chapter3', 1),
(17, 'Chapter4', 1);
Solution
select coalesce(ch.Name, co.Name) as [Course]
from course co
join chapter ch
on ch.c_id = co.id
group by co.Name, ch.Name with rollup
having grouping(co.Name) <> 1
order by co.Name, ch.Name;
For some background on how this solution works, have a look at this fiddle.
I have a table called 'bbe.case' with the following example data:
|---------------------|------------------|------------------|
| Id | Name | Phone |
|---------------------|------------------|------------------|
| 3455 | Johny | `123456 |
|---------------------|------------------|------------------|
| 3457 | Dora | 342754 |
|---------------------|------------------|------------------|
Instead having the real name in the Name column, I would like to change to 'Name 1', 'Name 2', 'Name 3' ... 'Name 1003' and so on, like the following:
|---------------------|------------------|------------------|
| Id | Name | Phone |
|---------------------|------------------|------------------|
| 3455 | Name 1 | 123456 |
|---------------------|------------------|------------------|
| 3457 | Name 2 | 342754 |
|---------------------|------------------|------------------|
'
'
'
|---------------------|------------------|------------------|
| 4453 | Name 999 | 12345 |
|---------------------|------------------|------------------|
| 4454 | Name 1000 | 345754 |
|---------------------|------------------|------------------|
Appreciate any guidance on this.
I hope this sample match your requiremnts:
CREATE TABLE #TempTbl (
[Id] int,
[Name] nvarchar(255),
[Phone] nvarchar(255)
)
INSERT INTO #TempTbl
VALUES
(20, 'Johny', '514545'),
(30, 'Hassan', '514545'),
(40, 'Yahya', '514545'),
(50, 'Waleed', '514545'),
(60, 'Shreem', '514545')
UPDATE t
SET t.[Name] = d.[NewName]
FROM #TempTbl t JOIN (
SELECT t.[Id], CONCAT('Name ', ROW_NUMBER() OVER (ORDER BY [Id])) AS 'NewName', t.Phone
FROM #TempTbl t
) d ON t.[Id] = d.[Id]
SELECT * FROM #TempTbl
I am creating a code to join two different tables under a certain condition. The tables look like this
(TABLE 2)
date | deal_code | originator | servicer | random |
-----------------------------------------------------
2011 | 001 | commerzbank | SPV1 | 1 |
2012 | 001 | commerzbank | SPV1 | 12 |
2013 | 001 | commerzbank | SPV1 | 7 |
2013 | 005 | unicredit | SPV2 | 7 |
and another table
(TABLE 1)
date | deal_code | amount |
---------------------------
2011 | 001 | 100 |
2012 | 001 | 100 |
2013 | 001 | 100 |
2013 | 005 | 200 |
I would like to have this as the final result
date | deal_code | amount | originator | servicer | random |
--------------------------------------------------------------
2013 | 001 | 100 | commerzbank | SPV1 | 7 |
2013 | 005 | 200 | unicredit | SPV2 | 7 |
I created the following code
select q1.deal_code, q1.date
from table1 q1
where q1.date = (SELECT MAX(t4.date)
FROM table1 t4
WHERE t4.deal_code = q1.deal_code)
that gives me:
(TABLE 3)
date | deal_code | amount |
---------------------------
2013 | 001 | 100 |
2013 | 005 | 200 |
That is the latest observation for table 1, now I would like to have the originator and servicer information given the deal_code and date. Any suggestion? I hope to have been clear enough. Thanks.
This should do what you are looking for. Please be careful when naming columns. Date is a reserved word and is too ambiguous to be a good name for a column.
declare #Something table
(
SomeDate int
, deal_code char(3)
, originator varchar(20)
, servicer char(4)
, random int
)
insert #Something values
(2011, '001', 'commerzbank', 'SPV1', 1)
, (2012, '001', 'commerzbank', 'SPV1', 12)
, (2013, '001', 'commerzbank', 'SPV1', 7)
, (2013, '005', 'unicredit ', 'SPV2', 7)
declare #SomethingElse table
(
SomeDate int
, deal_code char(3)
, amount int
)
insert #SomethingElse values
(2011, '001', '100')
, (2012, '001', '100')
, (2013, '001', '100')
, (2013, '005', '200')
select x.SomeDate
, x.deal_code
, x.originator
, x.servicer
, x.random
, x.amount
from
(
select s.SomeDate
, s.deal_code
, s.originator
, s.servicer
, s.random
, se.amount
, RowNum = ROW_NUMBER()over(partition by s.deal_code order by s.SomeDate desc)
from #Something s
join #SomethingElse se on se.SomeDate = s.SomeDate and se.deal_code = s.deal_code
) x
where x.RowNum = 1
Looks like this would work:
DECLARE #MaxYear INT;
SELECT #MaxYear = MAX(date)
FROM table1 AS t1
INNER JOIN table2 AS t2
ON t1.deal_code = t2.deal_code;
SELECT t1.date,
t1.deal_code,
t1.amount,
t2.originator,
t2.servicer,
t2.random
FROM table1 AS t1
INNER JOIN table2 AS t2
ON t1.date = #MaxYear
AND t1.deal_code = t2.deal_code;
I agree with Sean Lange about the date column name. His method gets around the dependency on the correlated sub-query, but at the heart of things, you really just need to add an INNER JOIN to your existing query in order to get the amount column into your result set.
select
q2.date,
q2.deal_code,
q1.amount,
q2.originator,
q2.servicer,
q2.random
from
table1 q1
join
table2 q2
on q1.date = q2.date
and q1.deal_code = q2.deal_code
where q1.date = (SELECT MAX(t4.date)
FROM table1 t4
WHERE t4.deal_code = q1.deal_code)
Compare historical rows (LAG rows based on ResultChngDt) and combine changed column values to single column. Looking for help in writing elegant/efficient SQL Server 2016 TSQL Code(without cursors).
I have a table with the structure and data like this:
+----+-------+--------------+---------------+--------+--------+--------------+
| ID | RepID | CollctedDate | CompletedDate | Result | Tcode | ResultChngDt |
+----+-------+--------------+---------------+--------+--------+--------------+
| 1 | 101 | 11/20/2017 | 12/13/2017 | | L-2190 | 12/13/2017 |
| 1 | 101 | 11/22/2017 | 12/15/2017 | POS | L-Afb | 1/5/2018 |
| 1 | 102 | 11/22/2017 | 12/15/2017 | | L-2191 | 12/15/2017 |
| 1 | 102 | 11/22/2017 | 12/15/2017 | POS | L-2192 | 12/31/2017 |
+----+-------+--------------+---------------+--------+--------+--------------+
I need to generate a report/result as follows:
+----+-------+---------------------------+--------------------------+--+
| ID | RepID | Previous | Current | |
+----+-------+---------------------------+--------------------------+--+
| 1 | 101 | CollctedDate:11/20/2017 | CollctedDate:11/22/2017 | |
| | | CompletedDate:12/13/2017 | CompletedDate:12/15/2017 | |
| | | Result: | Result:POS | |
| | | Tcode:L-2190 | Tcode:L-Afb | |
| 1 | 102 | CollctedDate:11/22/2017 | CollctedDate:11/22/2017 | |
| | | CompletedDate:12/15/2017 | CompletedDate:12/15/2017 | |
| | | Result: | Result:POS | |
| | | Tcode:L-2191 | Tcode:L-2192 | |
+----+-------+---------------------------+--------------------------+--+
CREATE TABLE [dbo].[Table1]
(
[ID] INT NULL,
[RepID] INT NULL,
[CollctedDate] DATETIME NULL,
[CompletedDate] DATETIME NULL,
[Result] VARCHAR(3) NULL,
[Tcode] VARCHAR(10) NULL,
[ResultChngDt] DATETIME NULL
) ON [PRIMARY];
GO
INSERT INTO [dbo].[Table1] ([ID], [RepID], [CollctedDate], [CompletedDate], [Result], [Tcode], [ResultChngDt])
VALUES (1, 101, N'11/20/2017', N'12/13/2017', N'', N'L-2190', N'12/13/2017')
, (1, 101, N'11/22/2017', N'12/15/2017', N'POS', N'L-Afb', N'1/5/2018')
, (1, 102, N'11/22/2017', N'12/15/2017', N'', N'L-2191', N'12/15/2017')
, (1, 102, N'11/22/2017', N'12/15/2017', N'POS', N'L-2192', N'12/31/2017')
Here's my query for your question:
WITH cte_LEADLAG AS(
SELECT ID,
RepID,
CollctedDate,
CompletedDate,
Result,
Tcode,
ResultChngDt,
CONCAT('CollectedDate:',CAST(CollctedDate AS DATETIME2), ' CompletedDate:', CAST(CompletedDate AS DATETIME2), ' Result:', Result, ' Tcode', Tcode) AS dates,
LAG(CollctedDate) OVER(PARTITION BY RepID ORDER BY CollctedDate) AS 'LAGCollectedDate' ,
lead(CollctedDate) OVER(PARTITION BY RepID ORDER BY CollctedDate) AS 'LEADCollectedDate',
LAG(CompletedDate) OVER(PARTITION BY RepID ORDER BY CompletedDate) AS 'LAGCompDate' ,
lead(CompletedDate) OVER(PARTITION BY RepID ORDER BY CompletedDate) AS 'LEADcompDate' ,
LEAD(Result) OVER(PARTITION BY RepID ORDER BY CompletedDate) AS 'LEADResult' ,
LEAD(Tcode) OVER(PARTITION BY RepID ORDER BY CompletedDate) AS 'LEADTcode'
FROM #temp
),
cte_FINAL AS(
SELECT distinct ID,
RepID,
CASE WHEN cte.LAGCollectedDate IS NULL THEN CONCAT('CollectedDate:',CAST(CollctedDate AS DATETIME2), ' CompletedDate:', CAST(CompletedDate AS DATETIME2), ' Result:', Result, ' Tcode', Tcode) end AS 'Previous',
CASE WHEN cte.LEADCollectedDate IS not NULL THEN CONCAT('CollectedDate:',CAST(cte.LEADCollectedDate AS DATETIME2), ' CompletedDate:', CAST(LEADcompDate AS DATETIME2), ' Result:', cte.LEADResult, ' Tcode', cte.LEADTcode) end AS 'Current'
FROM cte_LEADLAG AS cte
WHERE cte.LEADCollectedDate IN (SELECT MAX(LEADCollectedDate) FROM cte_LEADLAG WHERE cte_LEADLAG.RepID = cte.RepID))
)
SELECT *
FROM cte_FINAL;
Result:
with data as (
select *, row_number() over (partition by RepID order by ResultChgDt desc) as rn
from dbo.Table1
)
select
from data as d1 left outer join data as d2 on d2.rn = d1.rn + 1
where d1.rn = 1 -- I suppose you only want the two most recent??
This gives you all the data you need in a single row. You can handle report formatting to suit whatever requirements you have in whatever tool you're using for that.
I have this table and data
CREATE TABLE #transactions (
[transactionId] [int] NOT NULL,
[accountId] [int] NOT NULL,
[dt] [datetime] NOT NULL,
[balance] [smallmoney] NOT NULL,
CONSTRAINT [PK_transactions_1] PRIMARY KEY CLUSTERED
( [transactionId] ASC)
)
INSERT #transactions ([transactionId], [accountId], [dt], [balance]) VALUES
(1, 1, CAST(0x0000A13900107AC0 AS DateTime), 123.0000),
(2, 1, CAST(0x0000A13900107AC0 AS DateTime), 192.0000),
(3, 1, CAST(0x0000A13A00107AC0 AS DateTime), 178.0000),
(4, 2, CAST(0x0000A13B00107AC0 AS DateTime), 78.0000),
(5, 2, CAST(0x0000A13D011D1860 AS DateTime), 99.0000),
(6, 2, CAST(0x0000A13F00000000 AS DateTime), 97.0000),
(7, 1, CAST(0x0000A13D0141E640 AS DateTime), 201.0000),
(8, 3, CAST(0x0000A1420094DD60 AS DateTime), 4000.0000),
(9, 3, CAST(0x0000A14300956A00 AS DateTime), 4100.0000),
(10, 3, CAST(0x0000A14700000000 AS DateTime), 4200.0000),
(11, 2, CAST(0x0000A14B00B84BB0 AS DateTime), 110.0000)
I need two queries.
For each transaction, I want to return in a query the most recent balance for each account, and an extra column with a SUM of each account balance at that point in time.
Same as 1 but grouped by date without the time portion. So the latest account balance at the end of each day (where there is a transaction in any account) for each account, but SUMed together as in 1.
Data above is sample data that I just made up, but my real table has hundreds of rows and ten accounts (which may increase soon). Each account has a unique accountId. Seems quite a tricky piece of SQL.
EXAMPLE
For 1. I need a result like this:
+---------------+-----------+-------------------------+---------+-------------+
| transactionId | accountId | dt | balance | sumBalances |
+---------------+-----------+-------------------------+---------+-------------+
| 1 | 1 | 2013-01-01 01:00:00.000 | 123 | 123 |
| 2 | 1 | 2013-01-01 01:00:00.000 | 192 | 192 |
| 3 | 1 | 2013-01-02 01:00:00.000 | 178 | 178 |
| 4 | 2 | 2013-01-03 01:00:00.000 | 78 | 256 |
| 5 | 2 | 2013-01-05 17:18:00.000 | 99 | 277 |
| 7 | 1 | 2013-01-05 19:32:00.000 | 201 | 300 |
| 6 | 2 | 2013-01-07 00:00:00.000 | 97 | 298 |
| 8 | 3 | 2013-01-10 09:02:00.000 | 4000 | 4298 |
| 9 | 3 | 2013-01-11 09:04:00.000 | 4100 | 4398 |
| 10 | 3 | 2013-01-15 00:00:00.000 | 4200 | 4498 |
| 11 | 2 | 2013-01-19 11:11:00.000 | 110 | 4511 |
+---------------+-----------+-------------------------+---------+-------------+
So, for transactionId 8, I take the latest balance for each account in turn and then sum them. AccountID 1: is 201, AccountId 2 is 97 and AccountId 3 is 4000. Therefore the result for transactionId 8 will be 201+97+4000 = 4298. When calculating the set must be ordered by dt
For 2. I need this
+------------+-------------+
| date | sumBalances |
+------------+-------------+
| 01/01/2013 | 192 |
| 02/01/2013 | 178 |
| 03/01/2013 | 256 |
| 05/01/2013 | 300 |
| 07/01/2013 | 298 |
| 10/01/2013 | 4298 |
| 11/01/2013 | 4398 |
| 15/01/2013 | 4498 |
| 19/01/2013 | 4511 |
+------------+-------------+
So on date 15/01/2013 the latest account balance for each account in turn (1,2,3) is 201,97,4200. So the result for that date would be 201+97+4200 = 4498
This gives your first desired resultset (SQL Fiddle)
WITH T
AS (SELECT *,
balance -
isnull(lag(balance) OVER (PARTITION BY accountId
ORDER BY dt, transactionId), 0) AS B
FROM #transactions)
SELECT transactionId,
accountId,
dt,
balance,
SUM(B) OVER (ORDER BY dt, transactionId ROWS UNBOUNDED PRECEDING) AS sumBalances
FROM T
ORDER BY dt;
It subtracts the current balance of the account from the previous balance to get the net difference then calculates a running total of those differences.
And that can be used as a base for your second result
WITH T1
AS (SELECT *,
balance -
isnull(lag(balance) OVER (PARTITION BY accountId
ORDER BY dt, transactionId), 0) AS B
FROM #transactions),
T2 AS (
SELECT transactionId,
accountId,
dt,
balance,
ROW_NUMBER() OVER (PARTITION BY CAST(dt AS DATE) ORDER BY dt DESC, transactionId DESC) AS RN,
SUM(B) OVER (ORDER BY dt, transactionId ROWS UNBOUNDED PRECEDING) AS sumBalances
FROM T1)
SELECT CAST(dt AS DATE) AS [date], sumBalances
FROM T2
WHERE RN=1
ORDER BY [date];
Part 1
; WITH a AS (
SELECT *, r = ROW_NUMBER()OVER(PARTITION BY accountId ORDER BY dt)
FROM #transactions t
)
, b AS (
SELECT t.*
, transamount = t.balance - ISNULL(t0.balance,0)
FROM a t
LEFT JOIN a t0 ON t0.accountId = t.accountId AND t0.r + 1 = t.r
)
SELECT transactionId, accountId, dt, balance
, sumBalance = SUM(transamount)OVER(ORDER BY dt, transactionId)
FROM b
ORDER BY dt
Part 2
; WITH a AS (
SELECT *, r = ROW_NUMBER()OVER(PARTITION BY accountId ORDER BY dt)
FROM #transactions t
)
, b AS (
SELECT t.*
, transamount = t.balance - ISNULL(t0.balance,0)
FROM a t
LEFT JOIN a t0 ON t0.accountId = t.accountId AND t0.r + 1 = t.r
)
, c AS (
SELECT transactionId, accountId, dt, balance
, sumBalance = SUM(transamount)OVER(ORDER BY CAST(dt AS DATE))
, r1 = ROW_NUMBER()OVER(PARTITION BY accountId, CAST(dt AS DATE) ORDER BY dt DESC)
FROM b
)
SELECT dt = CAST(dt AS DATE)
, sumBalance
FROM c
WHERE r1 = 1
ORDER BY CAST(dt AS DATE)