如何按日期检索重叠记录

时间:2017-10-25 14:59:05

标签: sql date sql-server-2008-r2

我有这些表

const keys: string[] = []; const values: number[] = []; function tryGet(key: string, out: (value: number) => void): void { const index = keys.indexOf(key); if (index >= 0) { out(values[index]); } } function test(): void { const key = "myValue"; tryGet(key, (value) => { console.log(`Key '${key}' exist with value ${value}`); }); }

employee(id, name)

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

我的记录在employeekey

中按日期重叠
key(id, code)

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

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

进度

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

3 个答案:

答案 0 :(得分:2)

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都表示为重叠的第二个+记录

+----+----+----+------------+-------+------------+------------+
|    | 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 |
+----+----+------------+-------+------------+------------+

答案 1 :(得分:2)

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

;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

答案 2 :(得分:1)

我会尝试Name

Public Sub Add(ByVal Name As String, ByVal Value As Variant)
    Dim new_milestone As Milestone
    Set new_milestone = New Milestone

    new_milestone.Name = Name
    new_milestone.Value = Value

    prvt_Milestones.Add new_milestone, Name
End Sub