SQL Server:使用优先级重叠的时间间隔填充范围

时间:2017-05-02 09:23:53

标签: sql-server date

我需要使用此表中的数据填写从2017-04-01到2017-04-30的范围,知道优先级最高的记录优先于优先级较低的记录

id     startValidity  endValidity  priority
-------------------------------------------
1004    2017-04-03    2017-04-30    1   
1005    2017-04-10    2017-04-22    2   
1010    2017-04-19    2017-04-23    3   
1006    2017-04-24    2017-04-28    2   
1008    2017-04-26    2017-04-28    3   

在实践中,我需要得到这样的结果:

id      startValidity  endValidity  priority
--------------------------------------------
1004    2017-04-03    2017-04-09    1   
1005    2017-04-10    2017-04-18    2   
1010    2017-04-19    2017-04-23    3   
1006    2017-04-24    2017-04-25    2   
1008    2017-04-26    2017-04-28    3   
1004    2017-04-29    2017-04-30    1   

2 个答案:

答案 0 :(得分:1)

现在无法想到任何优雅或更有效的解决方案。 。 。

-- Sample Table
declare @tbl table
(
    id      int,
    startValidity   date,
    endValidty  date,
    priority    int
)

-- Sample Data
insert into @tbl select 1004, '2017-04-03', '2017-04-30', 1
insert into @tbl select 1005, '2017-04-10', '2017-04-22', 2
insert into @tbl select 1010, '2017-04-19', '2017-04-23', 3
insert into @tbl select 1006, '2017-04-24', '2017-04-28', 2
insert into @tbl select 1008, '2017-04-26', '2017-04-28', 3

-- Query
; with 
date_range as -- find the min and max date for generating list of dates
(
    select  start_date = min(startValidity), end_date = max(endValidty)
    from    @tbl
),
dates as -- gen the list of dates using recursive CTE
(
    select  rn = 1, date = start_date
    from    date_range

    union all

    select  rn = rn + 1, date = dateadd(day, 1, d.date)
    from    dates d
    where   d.date  < (select end_date from date_range)
),
cte as -- for each date, get the ID based on priority
(
    select  *, grp = row_number() over(order by id) - rn
    from    dates d
            outer apply
            (
                select  top 1 x.id, x.priority
                from    @tbl x
                where   x.startValidity <= d.date
                and     x.endValidty    >= d.date
                order by x.priority desc
            ) t
)
-- final result
select  id, startValidity = min(date), endValidty = max(date), priority
from    cte
group by grp, id, priority
order by startValidity

答案 1 :(得分:0)

我不明白Calendar CTE或table的用途。 所以我没有使用任何递归CTE或日历。

可能我完全不理解这个要求。

尝试使用差异样本数据

declare @tbl table
(
    id      int,
    startValidity   date,
    endValidty  date,
    priority    int
)

-- Sample Data
insert into @tbl select 1004, '2017-04-03', '2017-04-30', 1
insert into @tbl select 1005, '2017-04-10', '2017-04-22', 2
insert into @tbl select 1010, '2017-04-19', '2017-04-23', 3
insert into @tbl select 1006, '2017-04-24', '2017-04-28', 2
insert into @tbl select 1008, '2017-04-26', '2017-04-28', 3
;With CTE as
(
select * ,ROW_NUMBER()over(order by startValidity)rn
from @tbl
)
,CTE1 as
(
select c.id,c.startvalidity,isnull(dateadd(day,-1, c1.startvalidity)
,c.endValidty) Endvalidity
,c.[priority],c.rn 
from cte c
left join cte c1
on c.rn+1=c1.rn
)

select  id,startvalidity,Endvalidity,priority from cte1
union ALL
select id,startvalidity,Endvalidity,priority from
(
select top 1 id,ca.startvalidity,ca.Endvalidity,priority from cte1
cross apply(
select top 1  
dateadd(day,1,endvalidity) startvalidity
,dateadd(day,-1,dateadd(month, datediff(month,0,endvalidity)+1,0)) Endvalidity
from cte1
order by rn desc)CA
order by priority
)t4
--order by startvalidity --if req