【问题标题】:Need to check dates are overlapping or not in sql server需要在 sql server 中检查日期是否重叠
【发布时间】:2017-11-04 17:34:55
【问题描述】:

下面是我的输入代码

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,日期重叠 21-11-2016 介于 18-07-2016 和 25-11-2016 之间,也 21-08-2016 介于 18-07-2016 和 25-11-2016 之间 因此查询应返回开始日期为 18-07-2016(分钟),结束日期为 重叠的日期为 2017 年 2 月 15 日(最大值)。 对于其余条目,它应该返回带有标志“N”的相同条目。

EMP_ID |项目名称 | 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

【问题讨论】:

  • 您在问题中注意到emp_id 10081503start_date 应该是2016-07-18(最小值),但您的“最终输出”显示2016-11-21
  • 感谢您的帮助..!

标签: sql sql-server


【解决方案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    |
+----+----------+--------------+------------+------------+------+

日历和数字表参考:

【讨论】:

  • @user3620085 乐于助人!
  • @user3620085 如果日期重叠,我也需要计算差距。
  • @user3620085 这不是对您要求的这个新事物的非常清楚的解释,但我已经更新了 rextester 演示。看看有没有你需要的:rextester.com/QKEMH32326
【解决方案2】:

感谢大家的帮助。!

在相同的情况下需要一些帮助,

遇到以下情况,

在这种情况下,我们将在 ALLOCATION DETAILS 中获得两个条目。这是因为资源被分配到两个不同的项目,但第一个分配项目的分配结束日期(在上面的示例中)与第二个分配项目的分配开始日期重叠。 因此,对于分配 1 的任期计算: Tenure (Alloc 1)=Alloc 开始日期 (Alloc 2) – Alloc 开始日期 (Alloc 1) 即,(17-11-2016) – (01-09-2016) = 77 分配 2 的任期计算没有变化。 在这里,最终条目将如下所示:

【讨论】:

    猜你喜欢
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2013-09-27
    相关资源
    最近更新 更多