2017-10-25 1 views
0

Ich habe diese TabellenWie durch Daten Überlappung Datensatz abzurufen

employee(id, name)

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

key(id, code)

I Aufzeichnungen haben, die

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 

Die von Terminen in employeekey überlappen emp1 und emp3 Überlappung in Datumsangaben von Schlüsselzuweisungen Ich möchte, dass eine Abfrage diese zurückgibt. Das war mein Fortschritt, aber ich bekomme alle Angestellten, die 2 oder mehr Schlüssel haben, auch wenn sie sich in Daten nicht wie in den obigen Ergebnissen überschneiden. Ich möchte nur diejenigen, die sich wie unten gezeigt überschneiden.

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 

Fortschritt

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 

Antwort

2

Ich denke, Sie eine Abfrage wie folgt verwendet werden:

;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

+0

Reiniger als meine Vereinigung. – xQbert

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; 

uns geben: Beachten Sie, dass beide IDs sind hier vertreten wie die Überlappung der 2. + Rekord

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

Wir beide bekommen könnte O Datensätze auf diese Weise verlauten.

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

Geben Sie uns:

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

Danke für Ihre Antwort. Ich möchte die zweite Ergebnismenge von meiner Frage ausgeben. Was ich gerade bekomme, ist das erste Ergebnis. Sie haben also diejenigen, die emp1 und emp3 überlappen, aber ich möchte auch alle zugeordneten Schlüssel auflisten. In diesem Fall kann ich nicht sehen k001 und k004 –

+0

1 und 4 sind da, wenn wir alle a. * Und b. * Sie werden feststellen, dass die IDs der beiden Datensätze in der ersten Ansatz vorhanden sind. Oder wir können die beiden Ergebnisse wie in meinem Update zusammenführen. – xQbert

+0

Ehrfürchtig, Danke! –

1

Ich würde versuchen, 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 
) 
+0

Hinweis ganz richtig. Gibt alle 6 Datensätze zurück. http://rexttester.com/EYBX22604 – xQbert

+0

stimmt, korrigiert –

+0

sieht gut aus. Kann die sauberste Antwort sein. – xQbert

Verwandte Themen