【问题标题】:Populate Id's Based on another table根据另一个表填充 ID
【发布时间】:2020-02-25 08:49:36
【问题描述】:

我有下表:

以上示例数据如下:

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

上面给了我以下结果:

我如何操作它看起来如下:

我试过rankntilerow_number,但没有一个能提供我需要的结果...

非常感谢您的帮助!

编辑

我已将上面的 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

但是可以看出,它看起来不像我的预期结果:

【问题讨论】:

  • 很高兴您将示例数据发布为 DDL+DML,但是这些图像无助于理解问题,它们只会让问题变得更难(至少对我而言)。当前输出旁边的所需输出的清晰文本表示将有更多帮助。
  • 道歉@ZoharPeled,我需要idYear,每个月重复NULL,但从我的EDIT可以看出,我的尝试给出了我错了idYear(最后一列)-希望能更好地解释它...?
  • 即从第 1 行到第 11 行,我需要 idYear 为 1,从第 12 行到第 23 行,我需要 idYear 为 2,等等。

标签: tsql sql-server-2017


【解决方案1】:

您可以尝试通过加入 YEAR(@years.dYearStartDate) 和 YEAR(month.EndOfMonth) 从 @years 表中获取每年的信息,如下所示:

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

【讨论】:

  • 不幸的是,这不起作用,因为根据我的@year 表,我的期间从 2014 年 8 月开始,到 2015 年 6 月结束,这是我面临的困境,期间需要为 1在这个特定的时间。对于 Period 2,我的开始日期是 2015 年 7 月,结束日期是 2015 年 6 月,应该是 2 的 idYear 等。
【解决方案2】:

我可以解决此问题的唯一方法是使用LEADEnd Date 添加到我的表中,这很有效。

如上所述,我可以在这些日期之间查询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

结果如下(最后一列是我需要的结果):

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-14
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    相关资源
    最近更新 更多