Jouw definitie:
activiteit uit groep B vindt altijd plaats na activiteit uit groep A.
.. houdt logisch in dat er per gebruiker 0 of 1 B-activiteit is na 1 of meer A-activiteiten. Nooit meer dan 1 B-activiteiten achter elkaar.
Je kunt het laten werken met een enkele vensterfunctie, DISTINCT ON
en CASE
, wat de snelste manier zou moeten zijn voor weinigen rijen per gebruiker (zie ook hieronder):
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<>viool hier
Een SQL CASE
uitdrukking is standaard NULL
indien geen ELSE
branch is toegevoegd, dus dat heb ik kort gehouden.
Uitgaande van time
is gedefinieerd NOT NULL
. Anders wilt u misschien NULLS LAST
. toevoegen . Waarom?
- Sorteren op kolom ASC, maar NULL-waarden eerst?
(activity LIKE 'A%' OR activity LIKE 'B%')
is uitgebreider dan activity ~ '^[AB]'
, maar doorgaans sneller in oudere versies van Postgres. Over patroonherkenning:
- Patroon komt overeen met LIKE, VERGELIJKBAAR MET of reguliere expressies in PostgreSQL
Voorwaardelijke vensterfuncties?
Dat is eigenlijk mogelijk . U kunt het geaggregeerde FILTER
. combineren clausule met de OVER
clausule van vensterfuncties. Echter :
-
De
FILTER
clausule zelf kan alleen werken met waarden uit de huidige rij. -
Wat nog belangrijker is,
FILTER
is niet geïmplementeerd voor pure echte functies zoalslead()
oflag()
(tot Postgres 13) - alleen voor geaggregeerde functies.
Als je het probeert:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres zal je vertellen:
FILTER is not implemented for non-aggregate window functions
Over FILTER
:
- Samengevoegde kolommen met extra (verschillende) filters
- Verwijzen naar huidige rij in FILTER-clausule van vensterfunctie
Prestaties
Voor enkele gebruikers met weinig rijen per gebruiker, vrijwel elke zoekopdracht is snel, zelfs zonder index.
Voor velen gebruikers en weinig rijen per gebruiker, moet de eerste zoekopdracht hierboven het snelst zijn. Zie:
- Selecteer de eerste rij in elke GROUP BY-groep?
Voor velen rijen per gebruiker zijn er (mogelijk veel ) snellere technieken, afhankelijk van de details van uw opstelling. Zie:
- Optimaliseer de GROUP BY-query om de laatste rij per gebruiker op te halen