我无法准确得到我需要的东西。以下是我的表格示例:
Plan_ID | PlanBeginDate | PlanEndDate |
1 | 1/1/2015 | 1/1/2016 |
2 | 1/1/2016 | 1/1/2017 |
3 | 1/1/2013 | 1/1/2014 |
4 | 1/1/2015 | 1/1/2016 |
SrvID | Srv_Plan_ID | Srv_Discipline_ID | SrvBeginDate | SrvEndDate |
1 | 1 | 1 | 1/1/2015 | 1/1/2016 |
2 | 1 | 3 | 1/1/2015 | 1/1/2016 |
3 | 2 | 2 | 1/1/2016 | 4/4/2016 |
4 | 2 | 2 | 4/5/2016 | 1/1/2017 |
5 | 3 | 1 | 1/1/2013 | 6/1/2013 |
6 | 3 | 2 | 1/1/2013 | 1/1/2014 |
7 | 4 | 3 | 1/1/2015 | 7/1/2016 |
8 | 4 | 3 | 8/1/2015 | 1/1/2016 |
我希望看到所有与其相关的每个不同学科的服务日期未涵盖日期的计划。
计划1不应出现,因为与其相关的两个学科都涵盖所有日期。
计划2不应出现,因为两个相关的服务具有相同的学科并且共同覆盖整个计划日期范围。
计划3应该出现一次,因为SrvID 5不包括整个计划日期范围。
计划4应该出现,因为7月份为纪律3发现了。
我需要一个选择语句,它将按照上述标准返回以下字段。
Plan_ID | PlanBeginDate | PlanEndDate |Srv_Discipline_ID | SrvBeginDate | SrvEndDate |
到目前为止,这就是我所拥有的。
Select Plan_ID, Srv_Discipline_ID, PlanBeginningDate, PlanEndDate, MIN(SrvBeginDate) EarliestStartDate, MAX(SrvEndDate) LatestEndDate
From dbo.Plan
JOIN Services
ON Plan_ID = Srv_Plan_ID
GROUP BY Plan_ID, Srv_Discipline_ID, PlanBeginDate, PlanEndDate
ORDER BY Plan_ID
答案 0 :(得分:0)
我想出了一种方法,但它涉及昂贵的递归CTE,将日期范围扩展为可以加入的个别日期。所以,要明确的是,我不希望这个查询的性能非常好。
注意:我还在我使用的测试数据中将SrvEndDate
的{{1}}值从SrvID = 7
修改为7/1/2016
。当你说7月份被揭露时,这一定是你的意图。
<强>设置强>
7/1/2015
<强>查询强>
create table Plans (
Plan_ID int not null primary key,
PlanBeginDate date not null,
PlanEndDate date not null
)
create table Services (
SrvID int not null primary key,
Srv_Plan_ID int not null,
Srv_Discipline_ID int not null,
SrvBeginDate date not null,
SrvEndDate date not null
)
alter table Services
add constraint Services_fk
foreign key (Srv_Plan_ID)
references Plans(Plan_ID)
insert into Plans (Plan_ID, PlanBeginDate, PlanEndDate)
values
(1, '2015-01-01', '2016-01-01'),
(2, '2016-01-01', '2017-01-01'),
(3, '2013-01-01', '2014-01-01'),
(4, '2015-01-01', '2016-01-01')
insert into Services (SrvID, Srv_Plan_ID, Srv_Discipline_ID, SrvBeginDate, SrvEndDate)
values
(1, 1, 1, '2015-01-01', '2016-01-01'),
(2, 1, 3, '2015-01-01', '2016-01-01'),
(3, 2, 2, '2016-01-01', '2016-04-04'),
(4, 2, 2, '2016-04-05', '2017-01-01'),
(5, 3, 1, '2013-01-01', '2013-06-01'),
(6, 3, 2, '2013-01-01', '2014-01-01'),
(7, 4, 3, '2015-01-01', '2015-07-01'),
(8, 4, 3, '2015-08-01', '2016-01-01')
<强>结果强>
with ServiceCTE as (
select Srv_Plan_ID, Srv_Discipline_ID, SrvEndDate, SrvBeginDate as SrvDate
from Services
union all
select Srv_Plan_ID, Srv_Discipline_ID, SrvEndDate, dateadd(day, 1, SrvDate) as SrvDate
from ServiceCTE
where SrvDate != SrvEndDate
), PlanCTE as (
select Plan_ID, PlanEndDate, PlanBeginDate as PlanDate
from Plans
union all
select Plan_ID, PlanEndDate, dateadd(day, 1, PlanDate) as PlanDate
from PlanCTE
where PlanDate != PlanEndDate
), UncoveredPlanDisciplineCTE as (
select distinct pcte.Plan_ID, s.Srv_Discipline_ID
from PlanCTE pcte
join (select distinct Srv_Plan_ID, Srv_Discipline_ID
from Services) s
on s.Srv_Plan_ID = pcte.Plan_ID
where not exists (select null
from ServiceCTE scte
where scte.Srv_Plan_ID = s.Srv_Plan_ID
and scte.Srv_Discipline_ID = s.Srv_Discipline_ID
and scte.SrvDate = pcte.PlanDate)
)
select p.Plan_ID, p.PlanBeginDate, p.PlanEndDate,
s.Srv_Discipline_ID, s.SrvBeginDate, s.SrvEndDate
from UncoveredPlanDisciplineCTE c
join Plans p
on p.Plan_ID = c.Plan_ID
join Services s
on s.Srv_Plan_ID = c.Plan_ID
and s.Srv_Discipline_ID = c.Srv_Discipline_ID
order by p.Plan_ID, s.Srv_Discipline_ID, s.SrvBeginDate
option (maxrecursion 0)