Combine Record by Id - sql-server

I am Using SQLServer2008.
Output of My Stored Procedure is :
--------------------------------------------------------
BrokerCode | MemberId | FY | SY | TY |
--------------------------------------------------------
104 | 24 | 1140 | 0.00 | 0.00 |
--------------------------------------------------------
104 | 24 | 1140 | 570 | 0.00 |
--------------------------------------------------------
104 | 30 | 500 | 0.00 | 0.00 |
--------------------------------------------------------
104 | 30 | 500 | 360 | 0.00 |
--------------------------------------------------------
And I want to result like :
--------------------------------------------------------
BrokerCode | MemberId | FY | SY | TY |
--------------------------------------------------------
104 | 24 | 1140 | 570 | 0.00 |
--------------------------------------------------------
104 | 30 | 500 | 360 | 0.00 |
--------------------------------------------------------
So i have tried using :
WITH CTE AS (
SELECT BrockerCode,
MemberId,
RN=ROW_NUMBER()OVER(PARTITION BY MemberId ORDER BY MemberID),
FY=MIN(FY)OVER(PARTITION BY MemberId),
SY=MIN(SY)OVER(PARTITION BY MemberId),
TY=MIN(TY)OVER(PARTITION BY MemberId)
FROM #tablePromotee )
SELECT MemberId,BrockerCode,FY,SY,TY FROM CTE WHERE RN = 1
but still it display wrong result...please help me..where i am wrong? Thanks.

Common Table Expression isn't really required here. A much simpler query:
SELECT
BrokerCode,
MemberId,
MAX(FY) AS FY,
MAX(SY) AS SY,
MAX(TY) AS TY
FROM YourTable
GROUP BY BrokerCode, MemberId
SQL FIDDLE DEMO

You can simply use "GROUP BY " in your query
Like,
SELECT BrockerCode,
MemberId,
MIN(FY)
MIN(SY)
MIN(TY)
FROM #tablePromotee GROUP BY BrockerCode, MemberId
There are multiple aggregate function on sql server you can use from them as per your requirement.

Try this,
SELECT BrockerCode,
MemberId, FY,SUM(SY),SUM(TY) FROM #tablePromotee Group By BrockerCode,
MemberId, FY

Simply using group by wont work as you may end up in getting o.oo values
change last line of your existing code as below, hope you want this.
SELECT MemberId,BrockerCode,FY,SY,TY FROM CTE WHERE RN = 1 and SY<>0
ROUP BY BrockerCode, MemberId

Try this one -
SELECT
MemberId
, BrockerCode
, FY = MAX(FY)
, SY = MAX(SY)
, TY = MAX(TY)
FROM (
SELECT
BrockerCode
, MemberId
, RN = ROW_NUMBER()OVER(PARTITION BY MemberId ORDER BY MemberID)
, FY = MIN(FY)OVER(PARTITION BY MemberId)
, SY = MIN(SY)OVER(PARTITION BY MemberId)
, TY = MIN(TY)OVER(PARTITION BY MemberId)
FROM #tablePromotee
)
WHERE RN = 1
GROUP BY
BrokerCode
, MemberId
Or try this -
SELECT TOP 1
BrockerCode
, MemberId
, FY = MAX(MIN(FY)OVER(PARTITION BY MemberId))
, SY = MAX(MIN(SY)OVER(PARTITION BY MemberId))
, TY = MAX(MIN(TY)OVER(PARTITION BY MemberId))
FROM #tablePromotee
GROUP BY
BrokerCode
, MemberId
ORDER BY MemberId

Related

SQL - How to combine rows

I have the following table which looks at calls and attendances. I got this by using union all on a 'calls' and 'attendances' tables and then used row number on the ID and ordered by dates.
Table1:
Type | ID | Call/AttendanceDate | RowNum
------------|----|---------------------|--------
Attendance | 12 | 2018-09-16 10:11:00 | 82
Call | 12 | 2018-09-18 14:11:47 | 83
Call | 12 | 2018-10-02 17:26:13 | 84
Call | 12 | 2018-10-05 14:58:31 | 85
Attendance | 12 | 2018-10-13 01:41:00 | 86
Call | 12 | 2018-10-13 02:39:12 | 87
Call | 12 | 2018-10-13 04:31:22 | 88
Attendance | 12 | 2018-10-13 14:29:00 | 89
Call | 12 | 2018-10-13 14:59:19 | 90
Attendance | 12 | 2018-10-15 15:50:00 | 91
The code I used for this is:
WITH CTE1 AS
(
SELECT 'Call' as [Type], ID, CallDate AS Date1
FROM CallsTable
UNION ALL
SELECT 'Attendance' as [Type], ID, AttendanceDate AS Date2
FROM AttendanceTable]
)
,CTE2 AS
(
SELECT [Type], Date1, ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date1 ASC) AS RowNum
FROM CTE1
)
--------------------------------OUTPUT--------------------------------
SELECT a.[Type], a.ID, a.Date1, a.RowNum
FROM CTE2 a
JOIN CTE2 b
ON a.ID= b.ID
AND a.RowNum = b.RowNum + 1
WHERE a.ID = '12'
ORDER BY ID, RowNum
I want to modify this to look like the below output, so that whenever an attendance follows a call, it should be in the same row.
Table2:
Type | ID | CallDate | RowNum | Type | AttendanceDate | RowNum
------|----|------------------|--------|------------|------------------|--------
NULL | 12 | NULL | NULL | Attendance | 16/09/2018 10:11 | 82
Call | 12 | 18/09/2018 14:11 | 83 | NULL | NULL | NULL
Call | 12 | 02/10/2018 17:26 | 84 | NULL | NULL | NULL
Call | 12 | 05/10/2018 14:58 | 85 | Attendance | 13/10/2018 01:41 | 86
Call | 12 | 13/10/2018 02:39 | 87 | NULL | NULL | NULL
Call | 12 | 13/10/2018 04:31 | 88 | Attendance | 13/10/2018 14:29 | 89
Call | 12 | 13/10/2018 14:59 | 90 | Attendance | 15/10/2018 15:50 | 91
Is this possible? What code could I use?
Use FULL JOIN
SELECT
*
FROM
(SELECT * FROM CTE2 WHERE Type = 'CALL') A
FULL JOIN
(SELECT * FROM CTE2 WHERE Type = 'ATTENDANCE') B
ON A.ID = B.ID AND A.RowNum = B.RowNum - 1
You can use APPLY :
SELECT C.[Type], C.ID, C.CallDate, C.RowNum,
(CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.[TYPE] end) [TYPE],
(CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.CallDate end) AttendanceDate,
(CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.RowNum end) RowNum
FROM CTE2 C OUTER APPLY
(SELECT TOP (1) C2.*
FROM CTE2 C2
WHERE C2.ID = C.ID AND C2.[Type] = 'Attendance' AND C2.RowNum > C.RowNum
ORDER BY C2.RowNum
) C2
WHERE C.ID = 12 AND C.[Type] = 'Call';
Not as elegant, but works for me, a table valued function
alter FUNCTION GetCallActivity()
RETURNS #activityTable TABLE
(
call_type varchar(16),
call_id int,
call_date datetime,
call_rownum int,
atnd_type varchar(16),
atnd_id int,
atnd_date datetime,
atnd_rownum int
)
AS
BEGIN
-- initialize the return table
insert into #activityTable
(call_type, call_id, call_date, call_rownum )
select a.type, a.id, a.activity_date, a.rownum
from stack_calls a
where a.type = 'Call'
order by a.activity_date;
-- match to the attendence recs to the call recs
update #activityTable
set atnd_type = b.type,
atnd_id = b.id,
atnd_date = b.activity_date,
atnd_rownum = b.rownum
from stack_calls b
join #activityTable a
on b.rownum = a.call_rownum + 1
where b.type = 'Attendance';
-- deal with the edge cases
insert into #activityTable
( atnd_type, atnd_id, atnd_date, atnd_rownum )
select x.type,
x.id,
x.activity_date,
x.rownum
from
(
select a.type,
a.id,
a.activity_date,
a.rownum,
lag(a.type, 1) over (order by a.activity_date) as prev_type
from stack_calls a
where a.type = 'Attendance'
) x
where x.prev_type is null
RETURN
END
GO

SQL Pivot table with string fields

I am new with SQL Pivot, so i would like to have a detail explaination regarding to it. My table is like the following:
PID | NAME | PlateNumber | COUNTRY|
------------------------------------------
111 | Alex | ab123456 | GB |
------------------------------------------
111 | Alex | fe123344 | ES |
------------------------------------------
111 | Alex | r223456e | US |
------------------------------------------
112 | Simon | t22er563 | GB |
------------------------------------------
112 | Simon | q32345ke | DE |
------------------------------------------
113 | Ben | ve923456 | IT |
------------------------------------------
And i would to have the result in the following format:
PID |NAME |PlateNumber1|PlateNumber2| PlateNumber3|COUNTRY1| COUNTRY2| COUNTRY3|
--------------------------------------------------------------------------------
111 | Alex | ab123456 | fe123344 | r223456e | GB | ES | US |
--------------------------------------------------------------------------------
112 | Simon | t22er563| q32345ke | | GB | DE | |
--------------------------------------------------------------------------------
113 | Ben | ve923456| | | IT | | |
--------------------------------------------------------------------------------
Could you please help me with this?
Thank you in advance!
The traditional cross tab / conditional aggregation version would be like so:
test setup: http://rextester.com/SKMUL25726
select
pid
, name
, PlateNumber1 = max(case when rn = 1 then PlateNumber end)
, PlateNumber2 = max(case when rn = 2 then PlateNumber end)
, PlateNumber3 = max(case when rn = 3 then PlateNumber end)
, Country1 = max(case when rn = 1 then Country end)
, Country2 = max(case when rn = 2 then Country end)
, Country3 = max(case when rn = 3 then Country end)
from (
select t.*
, rn=row_number() over (partition by PID order by platenumber)
from t
) as t
group by pid, name
returns:
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
| pid | name | PlateNumber1 | PlateNumber2 | PlateNumber3 | Country1 | Country2 | Country3 |
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
| 111 | Alex | ab123456 | fe123344 | r223456e | GB | ES | US |
| 113 | Ben | ve923456 | NULL | NULL | IT | NULL | NULL |
| 112 | Simon | q32345ke | t22er563 | NULL | DE | GB | NULL |
+-----+-------+--------------+--------------+--------------+----------+----------+----------+
Using PIVOT:
with your_table(PID , NAME , PlateNumber , Country) as (
select 111 , 'Alex' , 'ab123456' , 'GB' union all
select 111 , 'Alex' , 'fe123344' , 'ES' union all
select 111 , 'Alex' , 'r223456e' , 'US' union all
select 112 , 'Simon' , 't22er563' , 'GB' union all
select 112 , 'Simon' , 'q32345ke' , 'DE' union all
select 113 , 'Ben' , 've923456' , 'IT'
)
select pid,
name,
max(PlateNumber1) PlateNumber1,
max(PlateNumber2) PlateNumber2,
max(PlateNumber3) PlateNumber3,
max(Country1) Country1,
max(Country2) Country2,
max(Country3) Country3
from (
select *,
'Country' + cast(row_number() over (
partition by PID order by pnum
) as varchar(30)) cn
from (
select t.*,PlateNumber pnum,
'PlateNumber' + cast(row_number() over (
partition by PID order by PlateNumber
) as varchar(30)) pn
from your_table t
) t
pivot(max(PlateNumber) for pn in ([PlateNumber1], [PlateNumber2], [PlateNumber3])) x
) t
pivot(max(Country) for cn in ([Country1], [Country2], [Country3])) x
group by pid,
name;
Demo
If the PlateNumber count is not fixed of PID, you can use dynamic statement.
CREATE TABLE #tt(PID INT,[Name] VARCHAR(10),PlateNumber VARCHAR(10),Country VARCHAR(5))
INSERT INTO #tt
select 111 , 'Alex' , 'ab123456' , 'GB' union all
select 111 , 'Alex' , 'fe123344' , 'ES' union all
select 111 , 'Alex' , 'r223456e' , 'US' union all
select 112 , 'Simon' , 't22er563' , 'GB' union all
select 112 , 'Simon' , 'q32345ke' , 'DE' union all
select 113 , 'Ben' , 've923456' , 'IT'
DECLARE #SQL VARCHAR(max),#col VARCHAR(max)
---- Get the max line count of all the PID
DECLARE #MaxNumber INT =0
SELECT #MaxNumber=CASE WHEN COUNT(0)>#MaxNumber THEN count(0) ELSE #MaxNumber END FROM #tt AS t GROUP BY t.Name,t.PID
PRINT #MaxNumber
SELECT #col=ISNULL(#col+',','')+'PlateNumber'+LTRIM(sv.number)+',Country'+LTRIM(sv.number)
FROM master.dbo.spt_values AS sv WHERE sv.type='P' AND sv.number BETWEEN 1 AND #MaxNumber
PRINT #col
SET #SQL='
SELECT * FROM (
SELECT pid,[name],c.col_value,c.col_title+LTRIM(ROW_NUMBER()OVER(PARTITION BY t.PID,[name],c.col_title ORDER BY (SELECT 0))) AS col_title FROM #tt AS t
CROSS APPLY(VALUES(''PlateNumber'',t.PlateNumber),(''Country'',t.Country))c(col_title,col_value)
) AS t
PIVOT(MAX(col_value) FOR col_title IN ('+#col+')) p'
EXEC(#SQL)
pid name PlateNumber1 Country1 PlateNumber2 Country2 PlateNumber3 Country3
----------- ---------- ------------ ---------- ------------ ---------- ------------ ----------
111 Alex r223456e GB fe123344 ES ab123456 US
113 Ben ve923456 IT NULL NULL NULL NULL
112 Simon q32345ke DE t22er563 GB NULL NULL

Sum one column and subtract over second column

I want to display the subtraction of two columns. From the first column I need to get sum all value and substract with each value from the second column.
This is the table structure:
id | name | col1 | col2 | date
------------------------------------
432| xxx | 0 | 15 |2015-11-17
432| yyy | 10 | 30 |2015-11-19
432| zzz | 60 | 40 |2015-11-20
433| aaa | 0 | 60 |2015-11-17
433| bbb | 80 | 20 |2015-11-19
433| ccc | 60 | 10 |2015-11-20
Formula should go:
sum(col1) = 70 =>>> WHERE ID = 432
70 - col2 col3
-------------------------
=> 70 - 15 = 55
=> 70 - (30 + 15) = 25
=> 70 - (40 + 45) = -15
---------------------------
sum(col1) = 140 ===>> WHERE ID = 433
140 - col2 col3
-------------------------
=> 140 - 60 = 80
=> 140 - (60 + 20) = 60
=> 140 - (10 + 80) = 50
result is col3 and Output should be like as
id | name | col1 | col2 | col3 | date
-------------------------------------------
432| xxx | 0 | 15 | 55 | 2015-11-17
432| yyy | 10 | 30 | 25 | 2015-11-19
432| zzz | 60 | 40 | -15 | 2015-11-20
433| aaa | 0 | 60 | 80 | 2015-11-17
433| bbb | 80 | 20 | 60 | 2015-11-19
433| ccc | 60 | 10 | 50 | 2015-11-20
EDIT: What if I need the values ​​vary depending on the group as a 432 and 433 id column.
Schema Info
DECLARE #TEST TABLE
(
id INT,
name VARCHAR(10),
col1 INT,
col2 int
)
INSERT INTO #TEST VALUES
(432,'xxx',0, 15 ),
(432,'yyy',10, 30 ),
(432,'zzz',60, 40 ),
(433,'aaa',0, 60 ),
(433,'bbb',80, 20 ),
(433,'ccc',60, 10 )
Query
SELECT T.id ,
T.name ,
T.col1 ,
T.col2 ,
SUM(T.col1) OVER( PARTITION BY T.id ORDER BY T.id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
- SUM(T.col2) OVER ( PARTITION BY T.id ORDER BY T.id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS col3
FROM #TEST T;
Results
id | name | col1 | col2 | col3 |
---------------------------------
432 | xxx | 0 | 15 | 55 |
432 | yyy | 10 | 30 | 25 |
432 | zzz | 60 | 40 | -15 |
433 | aaa | 0 | 60 | 80 |
433 | bbb | 80 | 20 | 60 |
433 | ccc | 60 | 10 | 50 |
SQL Fiddle
This should work:
declare #total int = (select sum(col1) from Table)
select id, name, col1, col2, #total - (select sum(col2) from Table where date <= T.date) as col3, date from Table T
I was assuming you want to substract every time the previous total (based on the date). I hope this is OK.
You can use simple select query with cross apply
SELECT ID
,NAME
,COL1
,COL2
,A.C1 - (
SUM(COL2) OVER (
ORDER BY ID
)
) AS COL3
FROM TABLE1 T1
CROSS APPLY (
SELECT SUM(COL1) AS C1
FROM TABLE1 T2
) A
You can use two subqueries in SELECT fields list.
With the first you'll get a sum of all rows of your table named yourtable, in the second you'll get a sum of all rows before the current. So you can subtract two values.
Try this:
SELECT T.id, T.name, T.col1, T.col2,
ISNULL(
(SELECT SUM(T2.col1) FROM yourtable T2)
,0) -
ISNULL(
(SELECT SUM(T3.col2) FROM yourtable T3
WHERE T3.id <= T.id)
,0) as col3,
t.date
FROM yourtable T
Go on Sql fiddle example
EDIT
SELECT T.id, T.name, T.col1, T.col2,
ISNULL(
(SELECT SUM(T2.col1) FROM yourtable T2 where T2.id = T.id)
,0) -
ISNULL(
(SELECT SUM(T3.col2) FROM yourtable T3
WHERE T3.id = T.id AND T3.date <= T.date)
,0) as col3,
t.date
FROM yourtable T
Go on Sql Fiddle edited example
Pay attention: A deep edit can be a different question. Two queries are differents
Pay attention: it's no good a field named ID with repeated values

The highest value from list-distinct

Can anyone help me with query, I have table
vendorid, agreementid, sales
12001 1004 700
5291 1004 20576
7596 1004 1908
45 103 345
41 103 9087
what is the goal ?
when agreemtneid >1 then show me data when sales is the highest
vendorid agreementid sales
5291 1004 20576
41 103 9087
Any ideas ?
Thx
Well you could try using a CTE and ROW_NUMBER something like
;WITH Vals AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY AgreementID ORDER BY Sales DESC) RowID
FROM MyTable
WHERE AgreementID > 1
)
SELECT *
FROM Vals
WHERE RowID = 1
This will avoid you returning multiple records with the same sale.
If that was OK you could try something like
SELECT *
FROM MyTable mt INNER JOIN
(
SELECT AgreementID, MAX(Sales) MaxSales
FROM MyTable
WHERE AgreementID > 1
) MaxVals ON mt.AgreementID = MaxVals.AgreementID AND mt.Sales = MaxVals.MaxSales
SELECT TOP 1 WITH TIES *
FROM MyTable
ORDER BY DENSE_RANK() OVER(PARTITION BY agreementid ORDER BY SIGN (SIGN (agreementid - 2) + 1) * sales DESC)
Explanation
We break table MyTable into partitions by agreementid.
For each partition we construct a ranking or its rows.
If agreementid is greater than 1 ranking will be equal to ORDER BY sales DESC.
Otherwise ranking for every single row in partition will be the same: ORDER BY 0 DESC.
See how it looks like:
SELECT *
, SIGN (SIGN (agreementid - 2) + 1) * sales AS x
, DENSE_RANK() OVER(PARTITION BY agreementid ORDER BY SIGN (SIGN (agreementid - 2) + 1) * sales DESC) AS rnk
FROM MyTable
+----------+-------------+-------+-------+-----+
| vendorid | agreementid | sales | x | rnk |
+----------|-------------|-------+-------+-----+
| 0 | 0 | 3 | 0 | 1 |
| -1 | 0 | 7 | 0 | 1 |
| 0 | 1 | 3 | 0 | 1 |
| -1 | 1 | 7 | 0 | 1 |
| 41 | 103 | 9087 | 9087 | 1 |
| 45 | 103 | 345 | 345 | 2 |
| 5291 | 1004 | 20576 | 20576 | 1 |
| 7596 | 1004 | 1908 | 1908 | 2 |
| 12001 | 1004 | 700 | 700 | 3 |
+----------+-------------+-------+-------+-----+
Then using TOP 1 WITH TIES construction we leave only rows where rnk equals 1.
you can try like this.
SELECT TOP 1 sales FROM MyTable WHERE agreemtneid > 1 ORDER BY sales DESC
I really do not know the business logic behind agreement_id > 1. It looks to me you want the max sales (with ties) by agreement id regardless of vendor_id.
First, lets create a simple sample database.
-- Sample table
create table #sales
(
vendor_id int,
agreement_id int,
sales_amt money
);
-- Sample data
insert into #sales values
(12001, 1004, 700),
(5291, 1004, 20576),
(7596, 1004, 1908),
(45, 103, 345),
(41, 103, 9087);
Second, let's solve this problem using a common table expression to get a result set that has each row paired with the max sales by agreement id.
The select statement just applies the business logic to filter the data to get your answer.
-- CTE = max sales for each agreement id
;
with cte_sales as
(
select
vendor_id,
agreement_id,
sales_amt,
max(sales_amt) OVER(PARTITION BY agreement_id) AS max_sales
from
#sales
)
-- Filter by your business logic
select * from cte_sales where sales_amt = max_sales and agreement_id > 1;
The screen shot below shows the exact result you wanted.

Display Data as Ledger

I am using SQL Server 2008. I have a table AdvanceEntry.
--------------------------------------------------------------------------------
Code | PaidDate | Amount | ReceiveDate | ReceiveAmount
--------------------------------------------------------------------------------
102 | 15-04-2004 | 3000 | 20-04-2004 | 2000
104 | 23-05-2006 | 1000 | NULL | 0.00
104 | 25-05-2005 | 1500 | 12-06-2005 | 500
When any person tack the Loan then Loan amount is stored in the Amount column and date is stored in PaidDate and person code is stored in Code column. When that person gives back the amount then that amount is stored in ReceiveAmount and date is stored in ReceiveDate.
Now I want to create a report like ledger of a specific code.
For example code 102
----------------------------------------------------------------------------
PaidDate / ReceiveDate | Amount | ReceiveAmount | Balance
----------------------------------------------------------------------------
15-04-2004 | 3000 | 0 | 3000
20-04-2004 | 0 | 2000 | 1000
And for code 104
----------------------------------------------------------------------------
PaidDate / ReceiveDate | Amount | ReceiveAmount | Balance
----------------------------------------------------------------------------
23-05-2006 | 1000 | 0 | 1000
25-05-2005 | 1500 | 0 | 2500
12-06-2005 | 0 | 500 | 2000
How can I do this? Please help me.. Thanks
Here's one way of doing it:
with Paid as
(
select Code
, PaidDate
, Amount
from AdvanceEntry
where PaidDate is not null
), Received as
(
select Code
, ReceiveDate
, ReceiveAmount
from AdvanceEntry
where ReceiveDate is not null
), Details as
(
select Code = coalesce(p.Code, r.Code)
, CodeDate = coalesce(p.PaidDate, r.ReceiveDate)
, Amount = sum(p.Amount)
, ReceiveAmount = sum(r.ReceiveAmount)
from Paid p
full join Received r on p.PaidDate = r.ReceiveDate and p.Code = r.Code
group by coalesce(p.Code, r.Code)
, coalesce(p.PaidDate, r.ReceiveDate)
)
select d.Code
, PayReceiveDate = d.CodeDate
, Amount = isnull(d.Amount, 0.0)
, ReceiveAmount = isnull(d.ReceiveAmount, 0.0)
, Balance = isnull(b.Balance, 0.0)
from Details d
outer apply (select Balance = sum(isnull(b.Amount, 0.0) - isnull(b.ReceiveAmount, 0.0))
from Details b where d.Code = b.Code and d.CodeDate >= b.CodeDate) b
order by d.Code, d.CodeDate
SQL Fiddle with demo.
It also looks like you had a slight typo in your data; I've changed it slightly in the fiddle to get your expected results.
Also worth mentioning that if you are only getting one pay/receive action per day per code you can get away without any GROUP BY in the query.
try this (untested):
;with cte as (
select Code, PaidDate as Date, Amount as Dr, 0 as Cr, Amount as Net
from Data where PaidDate is not null
union all
select Code, ReceivedData as Date, 0 as Dr, -ReceivedAmount as Cr, -ReceivedAmount as Net
from Data where ReceivedDate is not null
)
select
t1.*, sum(t2.Net) as Balance
from cte as t1
left join cte as t2 on t2.Code = t1.Code and t2.Date <= t1.Date
group by
t1.Code, t1.Date
having t1.Code = #Code

Resources