在一个结果行中选择给定时间间隔的具有ID历史记录的行

问题描述

StatusHistory包含:

ID      Status  DtSince DtUntil    
2415891  0     20200816 20200917
2415891  4     20200917 NULL
2415892  0     20200904 20200905
2415892  4     20200905 NULL

我需要为每个ID选择每个月初和月末的状态。 用户将输入所需的日期。例如:

用户输入-> @Month = '202009'

select语句必须返回dates 20200901 and 20201001的状态

对于新记录并具有dtSince> 20200901的记录,它应返回活动行。例如,对于2415892,它应返回4

因此@Month = 202009的结果集应为:

Id       BeginningOfMonth_status EndOfMonth_status 
2415891       0                         4
2415892       4                         4

这是我的解决方法

select * from
    (
    select * from 
        (
         select *,ROW_NUMBER() over (partition by id  order by dtSince desc) r from  
         dbo.StatusHistory
         where DtUntil  is null or (DtUntil <20201001and dtSince>=20200901) --2432290
        )x
     where x.r=1
)s1
inner join 
   (
   select * from 
       (
        select *,ROW_NUMBER() over (partition by id  order by dtSince desc) r from  
        dbo.StatusHistory
        where DtUntil  is null or (DtUntil <20201001and dtSince>=20200901) --2432290
       )x
   where x.r=2
   )s2
on s1.id = s2.id

问题:

1)有没有比我的代码复杂的东西了?

2)以上所述,我无法满足For records that are new and have dtSince>20200901的要求

解决方法

嗯。 。 。您可以使用where子句获取涵盖特定月份的所有行。然后使用row_number()枚举行和条件聚合:

select id,max(case when seqnum_asc = 1 then status end) as beginning_of_month,max(case when seqnum_desc = 1 then status end) as end_of_month
from (select t.*,row_nunber() over (partition by id order by dtsince) as seqnum_asc,row_nunber() over (partition by id order by dtsince desc) as seqnum_desc
      from t
      where dtsince < dateadd(month,1,convert(date,@Month + '01'))) and
            (dtuntil >= convert(date,@Month + '01') or dtuntil is null)
     ) t
group by id