Din definition:
aktivitet fra gruppe B foregår altid efter aktivitet fra gruppe A.
.. indebærer logisk, at der pr. bruger er 0 eller 1 B-aktivitet efter 1 eller flere A-aktiviteter. Aldrig mere end 1 B aktiviteter i rækkefølge.
Du kan få det til at fungere med en enkelt vinduesfunktion, DISTINCT ON
og CASE
, hvilket burde være den hurtigste måde for få rækker pr. bruger (se også nedenfor):
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<>spil her
En SQL CASE
udtryk er standard til NULL
hvis ingen ELSE
gren er tilføjet, så jeg holdt det kort.
Forudsat time
er defineret NOT NULL
. Ellers vil du måske tilføje NULLS LAST
. Hvorfor?
- Sortere efter kolonne ASC, men NULL-værdier først?
(activity LIKE 'A%' OR activity LIKE 'B%')
er mere omfattende end activity ~ '^[AB]'
, men typisk hurtigere i ældre versioner af Postgres. Om mønstermatchning:
- Mønstermatching med LIKE, SIMILAR TO eller regulære udtryk i PostgreSQL
Betingede vinduesfunktioner?
Det er faktisk muligt . Du kan kombinere det samlede FILTER
klausul med OVER
klausul af vinduesfunktioner. Men :
-
FILTER
selve klausulen kan kun fungere med værdier fra den aktuelle række. -
Endnu vigtigere,
FILTER
er ikke implementeret for rene ægte funktioner somlead()
ellerlag()
(op til Postgres 13) - kun for aggregerede funktioner.
Hvis du prøver:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres vil fortælle dig:
FILTER is not implemented for non-aggregate window functions
Om FILTER
:
- Samlet kolonner med yderligere (særskilte) filtre
- Referencer til den aktuelle række i FILTER-sætningen af vinduesfunktionen
Ydeevne
For få brugere med få rækker pr. bruger, stort set alle forespørgslen er hurtig, selv uden indeks.
For mange brugere og få rækker pr. bruger, bør den første forespørgsel ovenfor være hurtigst. Se:
- Vælg første række i hver GROUP BY-gruppe?
For mange rækker pr. bruger, der er (potentielt meget ) hurtigere teknikker, afhængigt af detaljerne i din opsætning. Se:
- Optimer GROUP BY-forespørgsel for at hente seneste række pr. bruger