如何按日期检索重叠记录

How to retrieve overlap record by dates

我有这些表格

employee(id, name)

employeekey(id, employeeid, keyid, startdate, enddate)

key(id, code)

我在 employeekey

中有按日期重叠的记录
id   employeeid   keyid   startdate   enddate
1    emp1         k001    01/01/2016  NULL
2    emp1         k002    02/06/2016  03/07/2016
3    emp2         k003    01/06/2016  30/06/2016
4    emp2         k003    01/07/2016  15/07/2016
5    emp3         k004    01/05/2016  15/05/2016
6    emp3         k005    10/05/2016  15/05/2016

emp1 和 emp3 在键分配日期上重叠我想查询 return。这是我的进步,但我得到了所有拥有 2 个或更多密钥的员工,即使他们没有像上面的结果那样在日期上重叠。我只想要那些重叠的,如下所示。

id   employeeid   keyid   startdate   enddate
1    emp1         k001    01/01/2016  NULL
2    emp1         k002    02/06/2016  03/07/2016
5    emp3         k004    01/05/2016  15/05/2016
6    emp3         k005    10/05/2016  15/05/2016

进度

select e.id as employeeid, e.name, k.id as keyid, ek.startdate, ek.enddate
from employee e 
inner join employeekey ek on ek.employeeid = e.id 
inner join key k on k.id = ek.keyid
where exists 
(
    select count(1), e2.id, e2.name
    from employee e2
    inner join employeekey2 ek2 on ek2.employeeid = e2.id
    where e.id = e2.id 
    group by e2.id, e2.name
    having count(e2.id) > 1
)
order by 1

DEMO:

SELECT A.ID, B.*
FROM employeeKey A
LEFT JOIN employeeKey  B
  on A.EmployeeID = B.EmployeeID
 and (B.StartDate between A.StartDate and Coalesce(A.EndDate,GetDate()) OR
      B.EndDate between A.StartDate and Coalesce(A.EndDate,GetDate()))
 and A.KeyID < B.KeyID
 Where B.ID is not null;

给我们:请注意,两个 ID 都在这里表示,重叠的第 2+ 条记录也是如此

+----+----+----+------------+-------+------------+------------+
|    | ID | id | employeeid | keyid | startdate  |  enddate   |
+----+----+----+------------+-------+------------+------------+
|  1 |  1 |  2 | emp1       | k002  | 2016/06/02 | 2016/07/03 |
|  2 |  5 |  6 | emp3       | k005  | 2016/05/10 | 2016/05/15 |
+----+----+----+------------+-------+------------+------------+

我们可以通过这种方式取回重叠的记录。

--Optional to just use A.ID and B.* to see all the IDs
--Select a.ID, B.*
SELECT B.*
FROM employeeKey A
LEFT JOIN employeeKey  B
  on A.EmployeeID = B.EmployeeID
 and (B.StartDate between A.StartDate and Coalesce(A.EndDate,GetDate()) OR
      B.EndDate between A.StartDate and Coalesce(A.EndDate,GetDate()))
 and A.KeyID < B.KeyID
 Where B.ID is not null

--You could exclude the union and add the optional select.
UNION ALL
SELECT A.*
FROM employeeKey A
LEFT JOIN employeeKey  B
  on A.EmployeeID = B.EmployeeID
 and (B.StartDate between A.StartDate and Coalesce(A.EndDate,GetDate()) OR
      B.EndDate between A.StartDate and Coalesce(A.EndDate,GetDate()))
 and A.KeyID < B.KeyID
 Where B.ID is not null
 Order by EmployeeID, KeyID
 ;

给我们:

+----+----+------------+-------+------------+------------+
|    | id | employeeid | keyid | startdate  |  enddate   |
+----+----+------------+-------+------------+------------+
|  1 |  1 | emp1       | k001  | 2016/01/01 | NULL       |
|  2 |  2 | emp1       | k002  | 2016/06/02 | 2016/07/03 |
|  3 |  5 | emp3       | k004  | 2016/05/01 | 2016/05/15 |
|  4 |  6 | emp3       | k005  | 2016/05/10 | 2016/05/15 |
+----+----+------------+-------+------------+------------+

我会尝试EXISTS

select id, employeeid, keyid, startdate, enddate
from employeekey ek1
where exists 
(
    select 1
    from employeekey ek2
    where ek1.id != ek2.id and
          ek1.employeeid = ek2.employeeid and
          ek2.startdate < Coalesce(ek1.enddate,GetDate()) and
          Coalesce(ek2.EndDate,GetDate()) > ek1.startdate   
)

我想你可以使用这样的查询:

;with overlaps as (
select *
from employeekey ek
where exists (
    select 1
    from employeekey eki
    where ek.id <> eki.id
      and ek.employeeid = eki.employeeid
      -- I use `<=` and `>=` instead of `between` because of date comparing problems with it 
      and ek.startdate >= eki.startdate
      and ek.startdate <= coalesce(eki.enddate, getdate())
    )
)
select *
from employeekey ek
where ek.employeeid in (
    select employeeid
    from overlaps
    );

SQL Server Fiddle Demo