Sql 如何按日期检索重叠记录

Sql 如何按日期检索重叠记录,sql,date,sql-server-2008-r2,Sql,Date,Sql Server 2008 R2,我有这些桌子 雇员ID,姓名 employeekeyid,employeeid,keyid,开始日期,结束日期 密钥ID,代码 我在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

我有这些桌子

雇员ID,姓名

employeekeyid,employeeid,keyid,开始日期,结束日期

密钥ID,代码

我在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在键分配的日期上重叠,我希望查询返回该值。这是我的进步,但我得到了所有拥有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
我们可以用这种方法把两个重叠的记录都找回来

--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
 ;
我们可以用这种方法把两个重叠的记录都找回来

--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
 ;
我会试试看

我会试试看


我认为您可以使用如下查询:

;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
    );

我认为您可以使用如下查询:

;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
    );

注意:完全正确。返回所有6条记录。注意:完全正确。返回所有6条记录。谢谢你的回答。我想要问题的第二个结果集输出。我现在得到的是第一个结果集。所以你得到了那些重叠emp1和emp3的密钥,但我想列出所有分配的密钥。在这种情况下,如果我们返回所有的a.*和b.*我看不到k001、k0041和4。您会注意到,在第一种方法中,两个记录的ID都存在。或者我们可以在我的更新中合并这两个结果。太棒了,谢谢@MaximusDecimus可能想看看shA.t的反应。清洁器似乎也能用。谢谢你的回答。我想要问题的第二个结果集输出。我现在得到的是第一个结果集。所以你得到了那些重叠emp1和emp3的密钥,但我想列出所有分配的密钥。在这种情况下,如果我们返回所有的a.*和b.*我看不到k001、k0041和4。您会注意到,在第一种方法中,两个记录的ID都存在。或者我们可以在我的更新中合并这两个结果。太棒了,谢谢@MaximusDecimus可能想看看shA.t的反应。清洁工似乎也能工作。
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
    );