Twoja definicja:
zajęcia z grupy B odbywają się zawsze po zajęciach z grupy A.
.. logicznie oznacza, że na użytkownika przypada 0 lub 1 aktywność B po 1 lub więcej aktywności A. Nigdy więcej niż 1 B czynności w kolejności.
Możesz sprawić, by działała z funkcją pojedynczego okna, DISTINCT ON
i CASE
, co powinno być najszybszym sposobem dla niewielu wierszy na użytkownika (patrz także poniżej):
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<>graj tutaj
SQL CASE
domyślne wyrażenie to NULL
jeśli nie ELSE
gałąź została dodana, więc zachowałem to krótko.
Zakładając time
jest zdefiniowany NOT NULL
. W przeciwnym razie możesz dodać NULLS LAST
. Dlaczego?
- Sortować według kolumny ASC, ale najpierw wartości NULL?
(activity LIKE 'A%' OR activity LIKE 'B%')
jest bardziej gadatliwy niż activity ~ '^[AB]'
, ale zazwyczaj szybciej w starszych wersjach Postgresa. Informacje o dopasowywaniu wzorców:
- Dopasowywanie wzorców za pomocą LIKE, SIMILAR TO lub wyrażeń regularnych w PostgreSQL
Warunkowe funkcje okna?
To właściwie możliwe . Możesz połączyć agregację FILTER
klauzula z OVER
klauzula funkcji okna. Jednak :
-
FILTER
sama klauzula może działać tylko z wartościami z bieżącego wiersza. -
Co ważniejsze,
FILTER
nie jest zaimplementowany dla czystych, oryginalnych funkcji, takich jaklead()
lublag()
(do Postgres 13) - tylko dla funkcji agregujących.
Jeśli spróbujesz:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres powie Ci:
FILTER is not implemented for non-aggregate window functions
O FILTER
:
- Agregacja kolumn z dodatkowymi (odrębnymi) filtrami
- Odwoływanie się do bieżącego wiersza w klauzuli FILTER funkcji okna
Wydajność
Dla niewielu użytkownicy z niewieloma wierszy na użytkownika, prawie dowolny zapytanie jest szybkie, nawet bez indeksu.
Dla wielu użytkowników i niewielu wierszy na użytkownika, pierwsze zapytanie powyżej powinno być najszybsze. Zobacz:
- Wybrać pierwszy wiersz w każdej grupie GROUP BY?
Dla wielu wierszy na użytkownika, jest (potencjalnie dużo ) szybsze techniki, w zależności od szczegółów konfiguracji. Zobacz:
- Zoptymalizuj zapytanie GROUP BY, aby pobrać ostatni wiersz na użytkownika