Заполнить идентификатор на основе другой таблицы - PullRequest
2 голосов
/ 25 февраля 2020

У меня есть следующая таблица:

Sample Data 1

Ниже приведены примеры данных:

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

Обратите внимание на Дата начала, где idYear = 1 - конец этого месяца. Я предоставил пример данных таким образом, поскольку именно так оно и есть в моей фактической таблице ...

Затем я генерирую Конец каждого месяца для всех периодов между этими месяцами с помощью этого сценария:

;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

Затем я присоединяюсь к cte с моей виртуальной таблицей, как показано ниже:

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

Выше приведены следующие результаты:

Results

Как мне манипулировать этим, чтобы выглядеть следующим образом:

Expected Results

Я пытался rank, ntile и row_number, но никто не дает мне требуемых результатов ...

Ваша помощь очень ценится!

РЕДАКТИРОВАТЬ

I select выше изменил следующее:

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

Но, как видно, это не похоже на мои ожидаемые результаты:

No Luck

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

Единственный способ обойти это, это добавить End Date к моей таблице, используя LEAD, что сработало.

С этим заявлением я могу запросить idYear между эти даты следующие:

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

Полный и окончательный код выглядит следующим образом:

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

Результаты выглядят следующим образом (последний столбец - результат, который мне нужен):

Results

0 голосов
/ 25 февраля 2020

Вы можете попробовать получить информацию за каждый год из таблицы @years, соединив YEAR (@ years.dYearStartDate) и YEAR (month.EndOfMonth), например так:

select a.EndOfMonth, b.idYear, b.cYearDescription, b.dYearStartDate
 from (
    select year(m.EndOfMonth) curYear, *
       from months m
     left join @years y  
       on  eomonth(dYearStartDate) = EndOfMonth) a
   inner join (select year(dYearStartDate) curYear, * from @years) b
     on a.curYear = b.curYear
   order by EndOfMonth
...