Reputation: 423
I have a system which stores the history of a balance in a history table. The table has the account number, sort code, balance, balance start date, balance end date. When a balance is updated an entry is created in the history table which shows what the balance, what the date was when that balance first started and the date which shows when the balances changed. So for example the table will show a balance of $100.00 and this balance ran from 07/10/2013 to 07/15/2013.
What I'm trying to do is get the sum of the balances for all sort codes on a specific day however the balance may not have changed on this date so I would need to return the closest prior date but I'm failing.
This is what I tried so far.
declare @sdate datetime
set @sdate = '06/08/2012' --mm/dd/yyyy
SELECT CONVERT(varchar(20),MAX(StartDate),103) as "Closest Start Date", Sort, SUM(Balance) AS "Sum of balances"
FROM BalanceHistory
WHERE StartDate <= convert(smalldatetime ,@sdate) AND SortCode <> 'ABC123456'
GROUP BY SortCode
SELECT FROM BalanceHistory would produce something like
AccountNumber, SortCode, Balance, StartDate, EndDate, RECID
00000001, srt010203, 100.00, 06/01/2013, 06/02/2013, RECID
00000001, srt010203, 110.00, 06/02/2013, 06/03/2013, RECID
00000001, srt010203, 120.00, 06/03/2013, 06/04/2013, RECID
00000002, srt010204, 200.00, 06/01/2013, 06/02/2013, RECID
00000003, srt010204, 300.00, 06/01/2013, 06/02/2013, RECID
00000004, srt010205, 400.00, 06/01/2013, 06/02/2013, RECID
00000005, srt010205, 500.00, 06/01/2013, 06/02/2013, RECID
Upvotes: 0
Views: 100
Reputation: 34774
You can do this without a JOIN
by using the ROW_NUMBER()
function (assuming SQL Server 2005 or newer):
DECLARE @sdate DATE
SET @sdate = '2012-06-08'
SELECT SortCode, SUM(Balance)'Sum of Balances'
FROM (SELECT AccountNumber,SortCode, Balance,ROW_NUMBER() OVER (PARTITION BY AccountNumber ORDER BY StartDate DESC)'RowRank'
FROM BalanceHistory
WHERE StartDate <= @sdate AND SortCode <> 'ABC123456'
)sub
WHERE RowRank = 1
GROUP BY SortCode
Demo: SQL Fiddle
The ROW_NUMBER()
function in the subquery assigns a 'RowRank' to the balance for each accountnumber, we order by StartDate DESC to get rank of '1' for the most recent balance for each accountnumber, the WHERE criteria limits it to most recent balance from the date you set in your variable. Then you use that rank in the outer query to limit only to that one balance.
Upvotes: 1
Reputation: 1065
This should work
Declare @table as table
(AccountNo int,
Balance money,
DateEntered datetime)
Declare @dt datetime
set @dt = '2013-07-01'
Insert into @table values(1, 100, '2013-04-01')
Insert into @table values(2, 200, '2013-04-01')
Insert into @table values(2, 300, '2013-05-01')
Insert into @table values(2, 400, '2013-06-01')
--select AccountNo, Max(Balance), Max(DateEntered) MaxDateEntered From @table where DateEntered <= @dt group by AccountNo
Select Sum(t.Balance) From @table t
inner join (select AccountNo, Max(Balance) Balance, Max(DateEntered) MaxDateEntered From @table where DateEntered <= @dt group by AccountNo) tm
on t.AccountNo = tm.AccountNo and t.DateEntered = tm.MaxDateEntered
enter code here
Upvotes: 0