以下是我的输入代码
ID EMP_ID PROJECT_NAME START_DATE END_DATE
1 10016351 ABC 22-12-2016 15-05-2017
2 10016351 ABC 01-09-2016 22-11-2016
1 10081503 RTBS AMaaS 21-11-2016 15-02-2017
2 10081503 RTBS AMaaS 18-07-2016 25-11-2016
3 10081503 RTBS AMaaS 21-08-2016 13-10-2016
4 10081503 RTBS AMaaS 03-02-2015 22-05-2015
1 10089293 RTBS PDaaS 17-02-2017 31-12-2017
2 10089293 RTBS PDaaS 13-06-2016 14-02-2017
我需要检查员工,日期是否重叠。如果是,那么它将返回最小开始日期和最大结束日期,并标记为' O'。
例如,对于emp_id = 10081503,日期重叠 2016年11月21日至2016年7月18日至2016年11月25日也是如此 2016年8月21日至2016年6月18日至2016年11月25日之间 所以查询应该将开始日期返回为18-07-2016(分钟)和结束日期为 15-02-2017(最大)日期重叠。 对于休息条目,它应返回带有标记' N'的相同条目。
EMP_ID | PROJECT_NAME | START_DATE | END_DATE |旗 10081503 | RTBS AMaaS | 21-11-2016 | 15-02-2017 | Ø 10081503 | RTBS AMaaS | 03-02-2015 | 22-05-2015 | Ñ
同样明智的我的最终输出应该是,
ID EMP_ID PROJECT_NAME START_DATE END_DATE FLAG
1 10016351 ABC 22-12-2016 15-05-2017 N
2 10016351 ABC 01-09-2016 22-11-2016 N
1 10081503 RTBS AMaaS 21-11-2016 15-02-2017 O
2 10081503 RTBS AMaaS 03-02-2015 22-05-2015 N
1 10089293 RTBS PDaaS 17-02-2017 31-12-2017 N
2 10089293 RTBS PDaaS 13-06-2016 14-02-2017 N
答案 0 :(得分:1)
使用outer apply()
返回重叠的第一个id
并按该值进行分组。使用row_number()
重新编号id
:
select
id = row_number() over (
partition by t.emp_id
order by min(start_date) desc
)
, t.emp_id
, t.project_name
, start_date = min(start_date)
, end_date = max(end_date)
, flag = max(case when x.id <> t.id then 'O' else 'N' end)
from t
outer apply (
select top 1 i.id
from t i
where i.Emp_Id = t.Emp_id
and i.End_Date > t.Start_Date
and t.End_Date > i.Start_Date
order by i.Start_Date
) x
group by t.emp_id, t.project_name, x.id
rextester演示:http://rextester.com/VHMZ91714
返回:
+----+----------+--------------+------------+------------+------+
| id | emp_id | project_name | start_date | end_date | flag |
+----+----------+--------------+------------+------------+------+
| 1 | 10016351 | ABC | 2016-12-22 | 2017-05-15 | N |
| 2 | 10016351 | ABC | 2016-09-01 | 2016-11-22 | N |
| 1 | 10081503 | RTBS AMaaS | 2016-07-18 | 2017-02-15 | O |
| 2 | 10081503 | RTBS AMaaS | 2015-02-03 | 2015-05-22 | N |
| 1 | 10089293 | RTBS PDaaS | 2017-02-17 | 2017-12-31 | N |
| 2 | 10089293 | RTBS PDaaS | 2016-06-13 | 2017-02-14 | N |
+----+----------+--------------+------------+------------+------+
以上将折叠相互重叠的范围,但如果您需要将仅在边缘重叠的多个范围折叠到一个范围内,我们可以使用日历或日期表,如下所示:
对于内存中只有152kb,您可以在表格中拥有30年的日期:
/* dates table */
declare @fromdate date = '20000101';
declare @years int = 30;
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate)))
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
into dbo.Dates
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date];
create unique clustered index ix_dbo_Dates_date on dbo.Dates([Date]);
如果您不想要创建日期表,您可以使用此查询生成如下日期:
declare @fromdate date = '20100101';
declare @thrudate date = getdate();
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (datediff(day, @fromdate, @thrudate)+1)
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by [Date]
)
, cte as (
select
t.emp_id
, t.project_name
, d.date
, rn = row_number() over (partition by t.emp_id, t.project_name order by d.date)-1
, flag = case when count(*) > 1 then 'O' else 'N' end
from t
inner join dates d
on d.date >= t.start_date
and d.date <= t.end_date
group by t.emp_id, t.project_name, d.date
)
select
id = row_number() over (partition by emp_id order by min(date) desc)
, emp_id
, project_name
, start_date = min(date)
, end_date = max(date)
, flag = max(flag)
from cte
group by emp_id, project_name, dateadd(day,-rn,date)
rextester演示:http://rextester.com/QKEMH32326
返回:
+----+----------+--------------+------------+------------+------+
| id | emp_id | project_name | start_date | end_date | flag |
+----+----------+--------------+------------+------------+------+
| 1 | 10016351 | ABC | 2016-12-22 | 2017-05-15 | N |
| 2 | 10016351 | ABC | 2016-09-01 | 2016-11-22 | N |
| 1 | 10081503 | RTBS AMaaS | 2016-07-18 | 2017-02-15 | O |
| 2 | 10081503 | RTBS AMaaS | 2015-02-03 | 2015-05-22 | N |
| 1 | 10089293 | RTBS PDaaS | 2017-02-17 | 2017-12-31 | N |
| 2 | 10089293 | RTBS PDaaS | 2016-06-13 | 2017-02-14 | N |
+----+----------+--------------+------------+------------+------+
日历和数字表参考:
答案 1 :(得分:0)
谢谢大家的帮助。
在相同的背景下需要一些帮助,
在这种情况下,我们将在ALLOCATION DETAILS中获得两个条目。这是因为资源被分配给两个不同的项目,但第一个分配项目的分配结束日期(在上面的例子中)与第二个分配项目的分配开始日期重叠。 因此,对于分配1的任期计算: 任期(Alloc 1)= Alloc开始日期(Alloc 2) - Alloc开始日期(Alloc 1) 即,(17-11-2016) - (01-09-2016)= 77 分配2的任期计算没有变化。 在这里,最终条目如下所示:
答案 2 :(得分:0)
不幸的是,第一个解决方案无法按所述方式运行,运行代码将仅导致三行(代码组甚至不重叠的日期):
-------------------------------------------------------------------
idItem qty shipToAddLine shipToCityStZip idItem qty
-------------------------------------------------------------------
DUR 82674 1 ZipCode DUR 82674 1
DUR 82674 1 ZipCode DUR 82674 1
DUR 82674 1 ZipCode DUR 82674 1
谁能提供可行的解决方案? 以下是一个示例代码,该代码无需创建任何表即可运行,仅用于测试:
id emp_id start_date end_date flag
1 10016351 2016-09-01 2017-05-15 O
1 10081503 2015-02-03 2017-02-15 O
1 10089293 2016-06-13 2017-12-31 O