Ich habe eine Tabelle mit Zahlen wie dieser (Status ist entweder FREI oder ZUGEWIESEN)
ID_SET-Nummernstatus ----------------------- 1 000001 ZUGEWIESEN 1 000002 KOSTENLOS 1 000003 ZUGEWIESEN 1 000004 KOSTENLOS 1 000005 KOSTENLOS 1 000006 ZUGEWIESEN 1 000007 ZUGEWIESEN 1 000008 KOSTENLOS 1 000009 KOSTENLOS 1 000010 KOSTENLOS 1 000011 ZUGEWIESEN 1 000012 ZUGEWIESEN 1 000013 ZUGEWIESEN 1 000014 KOSTENLOS 1 000015 ZUGEWIESEN
und ich muss "n" aufeinanderfolgende Zahlen finden, so dass für n = 3 die Abfrage zurückkehren würde
1 000008 KOSTENLOS 1 000009 KOSTENLOS 1 000010 KOSTENLOS
Es sollte nur die erste mögliche Gruppe jedes id_set zurückgeben (tatsächlich würde es nur für id_set pro Abfrage ausgeführt).
Ich habe WINDOW-Funktionen überprüft, einige Abfragen ausprobiert COUNT(id_number) OVER (PARTITION BY id_set ROWS UNBOUNDED PRECEDING)
, aber das ist alles, was ich habe :) Mir fiel keine Logik ein, wie man das in Postgres macht.
Ich habe darüber nachgedacht, eine virtuelle Spalte mit WINDOW-Funktionen zu erstellen, indem ich die vorhergehenden Zeilen für jede Nummer gezählt habe, bei der status = 'FREE' ist, und dann die erste Nummer ausgewählt habe, bei der count gleich meiner "n" -Nummer ist.
Oder gruppieren Sie Nummern nach Status, aber nur von einem ZUGEWIESENEN zu einem anderen ZUGEWIESENEN, und wählen Sie nur Gruppen aus, die mindestens "n" Nummern enthalten
BEARBEITEN
Ich habe diese Abfrage gefunden (und ein wenig geändert)
WITH q AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY id_set, status ORDER BY number) AS rnd,
ROW_NUMBER() OVER (PARTITION BY id_set ORDER BY number) AS rn
FROM numbers
)
SELECT id_set,
MIN(number) AS first_number,
MAX(number) AS last_number,
status,
COUNT(number) AS numbers_count
FROM q
GROUP BY id_set,
rnd - rn,
status
ORDER BY
first_number
das produziert Gruppen von FREE / ASSIGNED-Nummern, aber ich möchte alle Nummern nur von der ersten Gruppe haben, die die Bedingung erfüllt
id_set
oder nur eine? Bitte aktualisieren Sie Ihre Frage, wenn dies von Anfang an beabsichtigt war. (Damit andere die vollständigen Anforderungen einsehen und ihre Vorschläge unterbreiten oder ihre Antworten aktualisieren können.)Eine einfache und schnelle Variante:
Benötigt eine lückenlose Folge von Zahlen in
number
(wie in der Frage angegeben).Arbeitet für eine beliebige Anzahl von möglichen Werten in
status
außer'FREE'
, auch mitNULL
.Das Hauptmerkmal ist das Subtrahieren
row_number()
von,number
nachdem nicht qualifizierende Zeilen entfernt wurden. Aufeinanderfolgende Nummern enden in derselben Reihenfolgegrp
- und siegrp
sind garantiert auch in aufsteigender Reihenfolge .Dann können Sie
GROUP BY grp
die Mitglieder zählen. Da du scheinbar das erste Vorkommen habenORDER BY grp LIMIT 1
willst, erhältst du Startposition und Länge der Sequenz (kann> = n sein ).Reihe von Zeilen
Schauen Sie nicht ein weiteres Mal in der Tabelle nach, um eine tatsächliche Anzahl von Zahlen zu erhalten. Viel billiger mit
generate_series()
:Wenn Sie tatsächlich eine Zeichenfolge mit führenden Nullen wünschen, wie sie in Ihren Beispielwerten angezeigt wird, verwenden Sie
to_char()
denFM
Modifikator (Füllmodus):SQL Fiddle mit erweitertem Testfall und beiden Abfragen.
Eng verwandte Antwort:
quelle
Dies ist ein ziemlich allgemeiner Weg, um dies zu tun.
Denken Sie daran, dass dies davon abhängt, ob Ihre
number
Kolumne fortlaufend ist. Wenn es sich nicht um eine Windows-Funktion und / oder eine CTE-Typ-Lösung handelt, wird wahrscheinlich Folgendes benötigt:quelle
M.number-consec+1
(zB für 10 müsste es sein10-3+1=8
).number
Feldes beruht . Ich werde es korrigieren.EXISTS
könnte vereinfacht werden. Da wir nur sicherstellen müssen , jede n früheren Reihen vorhanden sind , können wir die fallenAND status = 'FREE'
. Und ich würde den Zustand in der 2. ändern ,EXISTS
umstatus <> 'FREE'
es gegen zusätzlichen Optionen in der Zukunft zu härten.Dies gibt nur die erste der 3 Zahlen zurück. Es ist nicht erforderlich, dass die Werte von
number
fortlaufend sind. Getestet bei SQL-Fiddle :Und dies zeigt alle Zahlen (wo es 3 oder mehr aufeinanderfolgende
'FREE'
Positionen gibt):quelle
In diesem Fall 5 aufeinanderfolgende Zahlen - daher muss die Differenz 4 oder mit anderen Worten
count(r3.number) = n
und seinr2.number = r1.number + n - 1
.Mit Joins:
quelle
JOIN
Syntax schreiben ?quelle
{ }
Knopf im Editor gedrückt habe. Genießen!