Tu definición:
la actividad del grupo B siempre tiene lugar después de la actividad del grupo A.
.. lógicamente implica que hay, por usuario, 0 o 1 actividad B después de 1 o más actividades A. Nunca más de 1 B actividades en secuencia.
Puede hacer que funcione con una función de ventana única, DISTINCT ON
y CASE
, que debería ser la forma más rápida para pocos filas por usuario (ver también a continuación):
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<>violín aquí
Un CASE
de SQL expresión por defecto es NULL
si no ELSE
se agrega la rama, así que lo mantuve breve.
Asumiendo time
se define NOT NULL
. De lo contrario, es posible que desee agregar NULLS LAST
. ¿Por qué?
- ¿Ordenar por columna ASC, pero los valores NULL primero?
(activity LIKE 'A%' OR activity LIKE 'B%')
es más detallado que activity ~ '^[AB]'
, pero generalmente más rápido en versiones anteriores de Postgres. Acerca de la coincidencia de patrones:
- Coincidencia de patrones con LIKE, SIMILAR TO o expresiones regulares en PostgreSQL
¿Funciones de ventana condicionales?
Eso es realmente posible . Puede combinar el agregado FILTER
cláusula con OVER
cláusula de funciones de ventana. Sin embargo :
-
El
FILTER
la cláusula en sí solo puede funcionar con valores de la fila actual. -
Más importante aún,
FILTER
no está implementado para funciones genuinas puras comolead()
olag()
(hasta Postgres 13) - solo para funciones agregadas.
Si intentas:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres le dirá:
FILTER is not implemented for non-aggregate window functions
Acerca de FILTER
:
- Columnas agregadas con filtros adicionales (distintos)
- Hacer referencia a la fila actual en la cláusula FILTER de la función de ventana
Rendimiento
Para pocos usuarios con pocos filas por usuario, prácticamente cualquiera la consulta es rápida, incluso sin índice.
Para muchos usuarios y pocos filas por usuario, la primera consulta anterior debería ser la más rápida. Ver:
- ¿Seleccionar la primera fila en cada grupo GROUP BY?
Para muchos filas por usuario, hay (potencialmente mucho ) técnicas más rápidas, dependiendo de los detalles de su configuración. Ver:
- Optimizar la consulta GROUP BY para recuperar la fila más reciente por usuario