Ihre Definition:
Aktivität aus Gruppe B findet immer nach Aktivität aus Gruppe A statt.
.. impliziert logischerweise, dass es pro Benutzer 0 oder 1 B-Aktivität nach 1 oder mehr A-Aktivitäten gibt. Nie mehr als 1 B Aktivitäten hintereinander.
Sie können es mit einer einzelnen Fensterfunktion, DISTINCT ON
, zum Laufen bringen und CASE
, was für wenige der schnellste Weg sein sollte Zeilen pro Benutzer (siehe auch unten):
SELECT name
, CASE WHEN a2 LIKE 'B%' THEN a1 ELSE a2 END AS activity
, CASE WHEN a2 LIKE 'B%' THEN a2 END AS next_activity
FROM (
SELECT DISTINCT ON (name)
name
, lead(activity) OVER (PARTITION BY name ORDER BY time DESC) AS a1
, activity AS a2
FROM t
WHERE (activity LIKE 'A%' OR activity LIKE 'B%')
ORDER BY name, time DESC
) sub;
db<>hier fummeln
Ein SQL CASE
Ausdruck ist standardmäßig NULL
wenn kein ELSE
Verzweigung hinzugefügt, also habe ich mich kurz gehalten.
Angenommen time
ist NOT NULL
definiert . Andernfalls möchten Sie vielleicht NULLS LAST
hinzufügen . Warum?
- Nach Spalte ASC sortieren, aber zuerst NULL-Werte?
(activity LIKE 'A%' OR activity LIKE 'B%')
ist ausführlicher als activity ~ '^[AB]'
, aber normalerweise schneller in älteren Versionen von Postgres. Über den Musterabgleich:
- Mustervergleich mit LIKE, SIMILAR TO oder regulären Ausdrücken in PostgreSQL
Bedingte Fensterfunktionen?
Das ist tatsächlich möglich . Sie können das Aggregat FILTER
kombinieren -Klausel mit dem OVER
Klausel von Fensterfunktionen. Allerdings :
-
Der
FILTER
-Klausel selbst kann nur mit Werten aus der aktuellen Zeile arbeiten. -
Noch wichtiger,
FILTER
ist für reine echte Funktionen wielead()
nicht implementiert oderlag()
(bis Postgres 13) - nur für Aggregatfunktionen.
Wenn Sie versuchen:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres sagt Ihnen:
FILTER is not implemented for non-aggregate window functions
Über FILTER
:
- Aggregierte Spalten mit zusätzlichen (unterschiedlichen) Filtern
- Verweis auf die aktuelle Zeile in der FILTER-Klausel der Fensterfunktion
Leistung
Für wenige Benutzer mit wenigen Zeilen pro Benutzer, so ziemlich beliebig Abfrage ist schnell, auch ohne Index.
Für viele Benutzer und wenige Zeilen pro Benutzer, die erste obige Abfrage sollte am schnellsten sein. Siehe:
- Erste Zeile in jeder GROUP BY-Gruppe auswählen?
Für viele Zeilen pro Benutzer gibt es (möglicherweise viele ) schnellere Techniken, abhängig von den Details Ihres Setups. Siehe:
- Optimieren Sie die GROUP BY-Abfrage, um die neueste Zeile pro Benutzer abzurufen