SQL
Fensterfunktionen
Suche…
Hinzufügen der insgesamt ausgewählten Zeilen zu jeder Zeile
SELECT your_columns, COUNT(*) OVER() as Ttl_Rows FROM your_data_set
Ich würde | Name | Ttl_Rows |
---|---|---|
1 | Beispiel | 5 |
2 | foo | 5 |
3 | Bar | 5 |
4 | baz | 5 |
5 | quux | 5 |
Anstatt zwei Abfragen zu verwenden, um einen Zähler als die Zeile abzurufen, können Sie ein Aggregat als Fensterfunktion verwenden und die vollständige Ergebnismenge als Fenster verwenden.
Dies kann als Grundlage für die weitere Berechnung verwendet werden, ohne dass zusätzliche Selbstverknüpfungen erforderlich sind.
Ein Flag setzen, wenn andere Zeilen eine gemeinsame Eigenschaft haben
Nehmen wir an, ich habe diese Daten:
Tischartikel
Ich würde | Name | Etikett |
---|---|---|
1 | Beispiel | unique_tag |
2 | foo | einfach |
42 | Bar | einfach |
3 | baz | Hallo |
51 | quux | Welt |
Ich möchte all diese Zeilen erhalten und wissen, ob ein Tag von anderen Zeilen verwendet wird
SELECT id, name, tag, COUNT(*) OVER (PARTITION BY tag) > 1 AS flag FROM items
Das Ergebnis wird sein:
Ich würde | Name | Etikett | Flagge |
---|---|---|---|
1 | Beispiel | unique_tag | falsch |
2 | foo | einfach | wahr |
42 | Bar | einfach | wahr |
3 | baz | Hallo | falsch |
51 | quux | Welt | falsch |
Falls Ihre Datenbank nicht OVER und PARTITION hat, können Sie dies verwenden, um dasselbe Ergebnis zu erzielen:
SELECT id, name, tag, (SELECT COUNT(tag) FROM items B WHERE tag = A.tag) > 1 AS flag FROM items A
Laufende Summe
Angesichts dieser Daten:
Datum | Menge |
---|---|
2016-03-12 | 200 |
2016-03-11 | -50 |
2016-03-14 | 100 |
2016-03-15 | 100 |
2016-03-10 | -250 |
SELECT date, amount, SUM(amount) OVER (ORDER BY date ASC) AS running
FROM operations
ORDER BY date ASC
werde dir geben
Datum | Menge | Laufen |
---|---|---|
2016-03-10 | -250 | -250 |
2016-03-11 | -50 | -300 |
2016-03-12 | 200 | -100 |
2016-03-14 | 100 | 0 |
2016-03-15 | 100 | -100 |
N die aktuellsten Zeilen über mehrere Gruppierungen abrufen
Angesichts dieser Daten
Benutzeridentifikation | Fertigstellungstermin |
---|---|
1 | 2016-07-20 |
1 | 2016-07-21 |
2 | 2016-07-20 |
2 | 2016-07-21 |
2 | 2016-07-22 |
;with CTE as
(SELECT *,
ROW_NUMBER() OVER (PARTITION BY User_ID
ORDER BY Completion_Date DESC) Row_Num
FROM Data)
SELECT * FORM CTE WHERE Row_Num <= n
Mit n = 1 erhalten Sie die letzte Zeile pro user_id
:
Benutzeridentifikation | Fertigstellungstermin | Row_Num |
---|---|---|
1 | 2016-07-21 | 1 |
2 | 2016-07-22 | 1 |
Suchen nach Datensätzen mit der Funktion LAG ()
Gegeben diese Beispieldaten:
ICH WÜRDE | STATUS | STATUS_TIME | STATUS_BY |
---|---|---|---|
1 | EIN | 2016-09-28-19.47.52.501398 | USER_1 |
3 | EIN | 2016-09-28-19.47.52.501511 | USER_2 |
1 | DREI | 2016-09-28-19.47.52.501517 | USER_3 |
3 | ZWEI | 2016-09-28-19.47.52.501521 | USER_2 |
3 | DREI | 2016-09-28-19.47.52.501524 | USER_4 |
Elemente, die durch ID
Werte identifiziert werden, müssen in der Reihenfolge von STATUS
'ONE' zu 'TWO' zu 'THREE' wechseln, ohne Status zu überspringen. Das Problem besteht darin, Benutzerwerte ( STATUS_BY
) zu finden, die gegen die Regel verstoßen, und sofort von "ONE" zu "DREI" wechseln.
Die analytische Funktion LAG()
hilft, das Problem zu lösen, indem für jede Zeile der Wert in der vorhergehenden Zeile zurückgegeben wird:
SELECT * FROM (
SELECT
t.*,
LAG(status) OVER (PARTITION BY id ORDER BY status_time) AS prev_status
FROM test t
) t1 WHERE status = 'THREE' AND prev_status != 'TWO'
Falls Ihre Datenbank nicht über LAG () verfügt, können Sie Folgendes verwenden, um dasselbe Ergebnis zu erzielen:
SELECT A.id, A.status, B.status as prev_status, A.status_time, B.status_time as prev_status_time
FROM Data A, Data B
WHERE A.id = B.id
AND B.status_time = (SELECT MAX(status_time) FROM Data where status_time < A.status_time and id = A.id)
AND A.status = 'THREE' AND NOT B.status = 'TWO'