Reputation: 1
I have daily data in the 'portfoliodata' table. Not all days have data so some month ends don't have data. I want to extract data from the latest day in each month that has data
declare @Portfolio as float
,@Date as date
,@Date12 as date
,@Date11 as date
,@Date10 as date
,@Date9 as date
,@Date8 as date
,@Date7 as date
,@Date6 as date
,@Date5 as date
,@Date4 as date
,@Date3 as date
,@Date2 as date
,@Date1 as date
set @Portfolio = 97900
select @Date = max(date) from portfoliodata
set @Date12 = EOMONTH(DATEADD(MONTH,-1,@Date))
set @Date11 = EOMONTH(DATEADD(MONTH,-2,@Date))
set @Date10 = EOMONTH(DATEADD(MONTH,-3,@Date))
set @Date9 = EOMONTH(DATEADD(MONTH,-4,@Date))
set @Date8 = EOMONTH(DATEADD(MONTH,-5,@Date))
set @Date7 = EOMONTH(DATEADD(MONTH,-6,@Date))
set @Date6 = EOMONTH(DATEADD(MONTH,-7,@Date))
set @Date5 = EOMONTH(DATEADD(MONTH,-8,@Date))
set @Date4 = EOMONTH(DATEADD(MONTH,-9,@Date))
set @Date3 = EOMONTH(DATEADD(MONTH,-10,@Date))
set @Date2 = EOMONTH(DATEADD(MONTH,-11,@Date))
set @Date1 = EOMONTH(DATEADD(MONTH,-12,@Date))
select * from portfoliodata
where Portfolio = @Portfolio and (
date = (select max(date) from portfoliodata where date < @Date12 and date > @Date11) or
date = (select max(date) from portfoliodata where date < @Date11 and date > @Date10) or
date = (select max(date) from portfoliodata where date < @Date10 and date > @Date9) or
date = (select max(date) from portfoliodata where date < @Date9 and date > @Date8) or
date = (select max(date) from portfoliodata where date < @Date8 and date > @Date7) or
date = (select max(date) from portfoliodata where date < @Date7 and date > @Date6) or
date = (select max(date) from portfoliodata where date < @Date6 and date > @Date5) or
date = (select max(date) from portfoliodata where date < @Date5 and date > @Date4) or
date = (select max(date) from portfoliodata where date < @Date4 and date > @Date3) or
date = (select max(date) from portfoliodata where date < @Date3 and date > @Date2) or
date = (select max(date) from portfoliodata where date < @Date2 and date > @Date1) or
date = (select max(date) from portfoliodata where date < @Date1))
The above code takes a long time to run
Upvotes: 0
Views: 72
Reputation: 1719
Just another way is to use a subquery in the where clause to get all the target dates.
Select *
From portfoliodata
Where Portfolio = 97900
And [date] In (Select Max([date]) From portfoliodata
Where Portfolio = 97900
Group by Year([date]), Month([date]))
you can limit the number of months as follows:
Declare @n Int = 12
Select *
From portfoliodata
Where Portfolio = 97900
And [date] In (Select Top (@n) Max([date]) From portfoliodata
Where Portfolio = 97900
Group by Year([date]), Month([date])
Order by 1 Desc)
Upvotes: 0
Reputation: 2265
If you just need the max day of each month, just put it into a CTE with ROW_NUMBER()
, and partition by the month of your date
field. We can eliminate the need for querying against date at all:
with recent as
(
select *
, ROW_NUMBER() over (partition by month(t.date) order by t.date desc) rn
from portfoliodata t
)
select *
from recent
where rn = 1
and portfolio = 97900
The where rn = 1
clause will give us the most recent date for each month. However, if you have multiple rows with the same date, this will arbitrarily order those.
If you want this to work over multiple years, include a partition on the year as well:
with recent as
(
select *
, ROW_NUMBER() over (partition by month(t.date), year(t.date) order by t.date desc) rn
from portfoliodata t
)
select *
from recent
where rn = 1
and portfolio = 97900
Upvotes: 3