SQL: Überlappende Datumsbereiche erkennen

Aus DBWiki
Wechseln zu: Navigation, Suche

Zurück zur Übersicht



Mit dem OVERLAPS-Operator können überlappende Datumsbereiche erkannt werden. Dabei gilt zu beachten, dass die Obergrenze nicht zum Bereich hinzugehört. Steht dieser Operator nicht im SQL-Dialekt zur Verfügung, muss man die Bedingungen selbst formulieren.


Es soll z.B. festgestellt werden, bei welchen Projekten eines Mitarbeiters sich Termine überlappen.

Lösung in Jet-SQL

Hinweis für Access-Anwender
Um die folgenden Abfragen selbst testen zu können, muss die Tabelle dual vorhanden sein.

Als Ausgangsbasis nehmen wir folgende Abfrage vw_projekt:

SELECT CLng(7782) AS ma_nr,
       #2018-02-09# AS pr_start,
       #2018-02-14# AS pr_ende,
       CLng(4) AS pr_nr
FROM   dual
UNION  ALL
SELECT 7782, #2018-02-13#, #2018-02-20#, 6 FROM dual
UNION  ALL
SELECT 7782, #2018-02-18#, #2018-02-23#, 5 FROM dual
UNION  ALL
SELECT 7782, #2018-02-22#, #2018-02-25#, 10 FROM dual
UNION  ALL
SELECT 7782, #2018-02-27#, #2018-03-01#, 15 FROM dual
UNION  ALL
SELECT 7839, #2018-02-10#, #2018-02-17#, 1 FROM dual
UNION  ALL
SELECT 7839, #2018-02-15#, #2018-02-18#, 9 FROM dual
UNION  ALL
SELECT 7839, #2018-02-20#, #2018-02-27#, 14 FROM dual
UNION  ALL
SELECT 7839, #2018-02-25#, #2018-02-28#, 3 FROM dual
UNION  ALL
SELECT 7839, #2018-02-28#, #2018-03-02#, 2 FROM dual
UNION  ALL
SELECT 7934, #2018-02-11#, #2018-02-12#, 7 FROM dual
UNION  ALL
SELECT 7934, #2018-02-12#, #2018-02-16#, 12 FROM dual
UNION  ALL
SELECT 7934, #2018-02-19#, #2018-02-20#, 11 FROM dual
UNION  ALL
SELECT 7934, #2018-02-23#, #2018-03-02#, 8 FROM dual
UNION  ALL
SELECT 7934, #2018-02-26#, #2018-03-03#, 13 FROM dual;
SELECT p1.ma_nr,
       'Projekt ' & Format( p1.pr_nr, '00' ) & ' überlappt Projekt ' & Format( p2.pr_nr, '00' ) AS info
FROM   vw_projekt AS p1,
       vw_projekt AS p2
WHERE  p1.ma_nr = p2.ma_nr AND
       p1.pr_start <= p2.pr_ende AND
       p1.pr_ende >= p2.pr_start AND
       p1.pr_nr < p2.pr_nr
ORDER  BY 1, p1.pr_start, p2.pr_start

Lösung für PostgreSQL

SELECT p1.ma_nr,
       'Projekt ' || to_char( p1.pr_nr, '00' ) || ' überlappt Projekt ' || to_char( p2.pr_nr, '00' ) AS info
FROM   vw_projekt AS p1,
       vw_projekt AS p2
WHERE  p1.ma_nr = p2.ma_nr AND
       p1.pr_nr < p2.pr_nr AND
       ( ( p1.pr_start, p1.pr_ende ) OVERLAPS ( p2.pr_start, p2.pr_ende ) OR
         p1.pr_ende  = p2.pr_start OR  -- weil sonst der letzte Tag nicht berücksichtigt wird
         p1.pr_start = p2.pr_ende )    -- dito; (man könnte das Ende der Bereiche um 1 Tag erweitern)
ORDER  BY 1, p1.pr_start, p2.pr_start

Hier ist ein entsprechender DBFiddle.

ma_nr info
7782 Projekt 04 überlappt Projekt 06
7782 Projekt 06 überlappt Projekt 05
7782 Projekt 05 überlappt Projekt 10
7839 Projekt 01 überlappt Projekt 09
7839 Projekt 14 überlappt Projekt 03
7839 Projekt 03 überlappt Projekt 02
7934 Projekt 07 überlappt Projekt 12
7934 Projekt 08 überlappt Projekt 13



Zurück zur Übersicht