I am trying to convert this query to a subquery without the ROW_NUMBER
function:
SELECT InvestorFundId, AsOfDate, AddedOn FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY InvestorFundId ORDER BY AsOfDate DESC, AddedOn DESC) AS HistoryIndex, * FROM [Investor.Fund.History] WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461) ) G WHERE HISTORYINDEX = 1
Basically this is selecting the most recent [Investor.Fund.History]
within a time period and depending on the status.
So far I have this:
SELECT InvestorFundId, MAX(AsOfDate) AS MaxAsOfDate, MAX(AddedOn) AS MaxAddedOn FROM [Investor.Fund.History] WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461) GROUP BY InvestorFundId
My query gives the incorrect results and it does this because when i use the MAX
function on multiple columns, it does not select the max based on the order of both columns like the ROW_NUMBER does, instead it selects the MAX
no matter both columns order positions.
For example, if I have a subset of data which looks like this:
| InvestorFundId | AsOfDate | AddedOn | | 1 | 2010-10-01 00:00:00.000 | 2012-04-18 09:29:33.277 | | 1 | 2006-11-01 00:00:00.000 | 2013-04-18 11:25:23.033 |
The ROW_NUMBER function will return the following:
| 1 | 2010-10-01 00:00:00.000 | 2012-04-18 09:29:33.277 |
Whereas my function returns this:
| 1 | 2010-10-01 00:00:00.000 | 2013-04-18 11:25:23.033 |
Which as you can see, is not actually a row in the table.
I would like my function to correctly return the row in the table based on the MAX
AsOfDATE
AND AddedOn
Can anyone help?
Advertisement
Answer
If you have a unique id that identifies each row, then you can do:
WITH ifh as ( SELECT InvestorFundId, AsOfDate, AddedOn FROM [Investor.Fund.History] WHERE DataStatusId = 1 AND AsOfDate <= (SELECT PeriodDate FROM [Fund.Period] WHERE Id = 5461) ) SELECT ifh.* FROM ifh WHERE ifh.? = (SELECT ? FROM ifh ifh2 WHERE ifh2.InvestorFundId = ifh.InvestorFundId ORDER BY AsOfDate DESC, AddedOn DESC FETCH FIRST 1 ROW ONLY );
The ?
is for the column that uniquely identifies each row.
This is also possible to do using APPLY
:
select ifh2.* from (select distinct InvestorFundId from ifh ) i cross apply (select top (1) ifh2.* from ifh ifh2 where fh2.InvestorFundId = i.InvestorFundId order by AsOfDate DESC, AddedOn DESC fetch first 1 row only ) ifh2;