I have the following Table:
The sample data for above is as following:
declare @years table (idYear int primary key identity, cYearDescription varchar(20), dYearStartDate datetime)
insert into @years (cYearDescription,dYearStartDate) values
('Year 1','2014-08-31')
, ('Year 2','2015-07-01')
, ('Year 3','2016-07-01')
, ('Year 4','2017-07-01')
, ('Year 5','2018-07-01')
, ('Year 6','2019-07-01')
select
*
from @years
Notice the Start Date for where idYear = 1
is the end of that month. I've provided the sample data this way, as it's exactly how it is in my actual table...
I then generate the End of each month for all the periods in between these months with this script:
;with cte as
(
select dateadd(day, nbr - 1, (select min(dYearStartDate) from @years)) CalendarDate
from ( select row_number() over ( order by c.object_id ) as nbr
from sys.columns c
) nbrs
where nbr - 1 <= datediff(day, (select min(dYearStartDate) from @years), (select max(dYearStartDate) from @years))
)
, months as (
select
eomonth(CalendarDate) EndOfMonth
from cte
group by eomonth(CalendarDate)
)
select
*
from months
I then join the cte
with my virtual table like following:
declare @years table (idYear int primary key identity, cYearDescription varchar(20), dYearStartDate datetime)
insert into @years (cYearDescription,dYearStartDate) values
('Year 1','2014-08-31')
, ('Year 2','2015-07-01')
, ('Year 3','2016-07-01')
, ('Year 4','2017-07-01')
, ('Year 5','2018-07-01')
, ('Year 6','2019-07-01')
;with cte as
(
select dateadd(day, nbr - 1, (select min(dYearStartDate) from @years)) CalendarDate
from ( select row_number() over ( order by c.object_id ) as nbr
from sys.columns c
) nbrs
where nbr - 1 <= datediff(day, (select min(dYearStartDate) from @years), (select max(dYearStartDate) from @years))
)
, months as (
select
eomonth(CalendarDate) EndOfMonth
from cte
group by eomonth(CalendarDate)
)
select
*
from months m
left join @years y on eomonth(dYearStartDate) = EndOfMonth
order by EndOfMonth
The above gives me the following results:
How do I manipulate this to look as follows:
I've tried rank
, ntile
and row_number
, but none give me the results I require...
Your assistance is much appreciated!
EDIT
I've altered the select
above to the following:
select
*
, isnull(idYear,lag(idYear) over (order by EndOfMonth)) idYear
, (select idYear from @years where year(dYearStartDate) = year(EndOfMonth)) idYear
from months m
left join @years y on eomonth(dYearStartDate) = EndOfMonth
order by EndOfMonth
But as can be seen, it's not looking like my expected results:
The only way I can work around this, was to add an End Date
to my table using LEAD
, which worked.
With that stated, I am able to query the idYear
between these dates as following:
select
*
, iif(idYear is null,(select idYear from LeadDateAdded where EndOfMonth between dYearStartDate and dYearEndDate),idYear) idYear
from months m
left join LeadDateAdded y on eomonth(dYearStartDate) = EndOfMonth
order by EndOfMonth
The full and final code looks like this:
declare @years table (idYear int primary key identity, cYearDescription varchar(20), dYearStartDate datetime)
insert into @years (cYearDescription,dYearStartDate) values
('Year 1','2014-08-31')
, ('Year 2','2015-07-01')
, ('Year 3','2016-07-01')
, ('Year 4','2017-07-01')
, ('Year 5','2018-07-01')
, ('Year 6','2019-07-01')
, ('Year 7','2020-07-01')
;with cte as
(
select dateadd(day, nbr - 1, (select min(dYearStartDate) from @years)) CalendarDate
from ( select row_number() over ( order by c.object_id ) as nbr
from sys.columns c
) nbrs
where nbr - 1 <= datediff(day, (select min(dYearStartDate) from @years), (select max(dYearStartDate) from @years))
)
, months as (
select
eomonth(CalendarDate) EndOfMonth
from cte
group by eomonth(CalendarDate)
)
, Years as (
select
idYear
, cYearDescription
, dYearStartDate
, cast(lead(eomonth(dYearStartDate)) over (order by idYear) as datetime) dYearEndDate
from @years
)
select
*
, iif(idYear is null,(select idYear from Years where EndOfMonth between dYearStartDate and dYearEndDate),idYear) idYear
from months m
left join Years y on eomonth(dYearStartDate) = EndOfMonth
order by EndOfMonth
The results are as following (Last Column is the result I needed):