我需要使用此表中的数据填写从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
答案 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