Вашето определение:
дейност от група B винаги се извършва след дейност от група A.
.. логично означава, че има, на потребител, 0 или 1 B активност след 1 или повече A дейности. Никога повече от 1 B дейности в последователност.
Можете да го накарате да работи с функция с един прозорец, DISTINCT ON
и CASE
, което би трябвало да е най-бързият начин за няколко редове на потребител (вижте също по-долу):
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<>цигулка тук
SQL CASE
изразът по подразбиране е NULL
ако няма ELSE
клонът е добавен, така че накратко.
Ако приемем time
е дефиниран NOT NULL
. В противен случай може да искате да добавите NULLS LAST
. Защо?
- Сортиране по колона ASC, но първо NULL стойности?
(activity LIKE 'A%' OR activity LIKE 'B%')
е по-подробно от activity ~ '^[AB]'
, но обикновено по-бърз в по-старите версии на Postgres. Относно съвпадението на шаблони:
- Съвпадение на образец с LIKE, SIMILAR TO или регулярни изрази в PostgreSQL
Условни функции на прозореца?
Това всъщност е възможно . Можете да комбинирате обобщения FILTER
клауза с OVER
клауза за функции на прозореца. Въпреки това :
-
FILTER
Самата клауза може да работи само със стойности от текущия ред. -
По-важното е
FILTER
не се прилага за чисти истински функции катоlead()
илиlag()
(до Postgres 13) - само за агрегатни функции.
Ако опитате:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres ще ви каже:
FILTER is not implemented for non-aggregate window functions
Относно FILTER
:
- Агрегирайте колони с допълнителни (отличителни) филтри
- Препраща се към текущия ред в клаузата FILTER на функцията на прозореца
Ефективност
Заняколко потребители смалко редове на потребител, почти всякакъв заявката е бърза, дори без индекс.
Замного потребители иняколко редове на потребител, първата заявка по-горе трябва да е най-бърза. Вижте:
- Изберете ли първия ред във всяка група GROUP BY?
Замного редове на потребител, има (потенциално много ) по-бързи техники, в зависимост от детайлите на вашата настройка. Вижте:
- Оптимизирайте заявката GROUP BY, за да извлечете последния ред на потребител