SQL: Sequentiell ansteigende Zahlenfolgen ermitteln

Aus DBWiki
Wechseln zu: Navigation, Suche

Zurück zur Übersicht



Gegeben sei eine fortlaufend numerierte Liste mit Werten. Es soll in einer Abfrage herausgefunden werden, welche aufeinanderfolgenden Werte jeweils um den Wert 1 zunehmen.

Allgemeine Lösung

Hinweis für Access-Anwender

Um die folgenden Abfragen selbst testen zu können, ist die Tabelle dual erforderlich.


Als Ausgangslage verwenden wir diese Abfrage vw_seq.

SELECT CLng(111) AS id, CLng(37) AS wert FROM dual
UNION  ALL
SELECT 112, 33 FROM dual
UNION  ALL
SELECT 113, 34 FROM dual
UNION  ALL
SELECT 114, 35 FROM dual
UNION  ALL
SELECT 115, 37 FROM dual
UNION  ALL
SELECT 116, 36 FROM dual
UNION  ALL
SELECT 117, 36 FROM dual
UNION  ALL
SELECT 118, 38 FROM dual
UNION  ALL
SELECT 119, 39 FROM dual
UNION  ALL
SELECT 120, 40 FROM dual
UNION  ALL
SELECT 121, 41 FROM dual
UNION  ALL
SELECT 122, 40 FROM dual
UNION  ALL
SELECT 123, 41 FROM dual
Wiki hinweis.png

Anmerkung: Abwender anderer Datenbanken als Access lassen jeweils das FROM dual weg.


Wir verwenden vw_seq in zwei zwei Instanzen (s1 und s2), um die niedrigste und höchste id einer Sequenz festzustellen. Als Randbedingung lässt sich daraus ableiten, dass s1.id kleiner s2.id sein muss. Die Tatsache, dass die Differenz aus wert und id innerhalb einer Sequenz immer einen konstanten Wert ergibt, kann in einer NOT EXISTS-Klausel genutzt werden. Darin werden Werte ausgeschlossen, die diesem Kriterium nicht genügen und zwischen angang und ende der Sequenz liegen, oder kleiner als der Startwert sind oder größer als der Endwert sind - aber das Kriterium der Sequenz erfüllen (wir wollen ja nur die Grenzwerte wissen).

Zielabfrage

SELECT s1.id AS anfang,
       s2.id AS ende,
       s2.id - s1.id + 1 AS groesse
FROM   vw_seq AS s1,
       vw_seq AS s2
WHERE  s1.id < s2.id AND
       NOT EXISTS( SELECT 'x'
                   FROM   vw_seq AS s3
                   WHERE  s3.wert - s3.id <> s1.wert - s1.id AND
                          s3.id BETWEEN s1.id AND s2.id OR
                          s3.id = s1.id - 1 AND
                          s3.wert - s3.id = s1.wert - s1.id OR
                          s3.id = s2.id + 1 AND
                          s3.wert - s3.id = s1.wert - s1.id )
anfang ende groesse
112 114 3
118 121 4
122 123 2



Zurück zur Übersicht