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;