Sua definição:
a atividade do grupo B sempre ocorre após a atividade do grupo A.
.. implica logicamente que há, por usuário, 0 ou 1 atividade B após 1 ou mais atividades A. Nunca mais de 1 B atividades em sequência.
Você pode fazê-lo funcionar com uma única função de janela,
DISTINCT ON
e CASE
, que deve ser o caminho mais rápido para poucos linhas por usuário (veja também abaixo):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<>mexa aqui
Um SQL
CASE
expressão padrão para NULL
se não houver ELSE
branch é adicionado, então eu mantive isso curto. Assumindo
time
está definido NOT NULL
. Caso contrário, você pode querer adicionar NULLS LAST
. Por quê? - Classificar por coluna ASC, mas primeiro com valores NULL?
(activity LIKE 'A%' OR activity LIKE 'B%')
é mais detalhado que activity ~ '^[AB]'
, mas normalmente mais rápido em versões mais antigas do Postgres. Sobre a correspondência de padrões:- Correspondência de padrões com LIKE, SIMILAR TO ou expressões regulares no PostgreSQL
Funções de janela condicional?
Isso é realmente possível . Você pode combinar o agregado
FILTER
cláusula com o OVER
cláusula de funções de janela. No entanto :-
OFILTER
A cláusula em si só pode funcionar com valores da linha atual.
-
Mais importante,FILTER
não é implementado para funções genuínas puras comolead()
oulag()
(até Postgres 13) - apenas para funções agregadas.
Se você tentar:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
O Postgres lhe dirá:
FILTER is not implemented for non-aggregate window functions
Sobre
FILTER
:- Colunas agregadas com filtros adicionais (distintos)
- Referenciando a linha atual na cláusula FILTER da função de janela
Desempenho
Para poucos usuários com poucos linhas por usuário, praticamente qualquer a consulta é rápida, mesmo sem index.
Para muitos usuários e poucos linhas por usuário, a primeira consulta acima deve ser mais rápida. Ver:
- Selecionar a primeira linha em cada grupo GROUP BY?
Para muitos linhas por usuário, há (potencialmente muito ) técnicas mais rápidas, dependendo dos detalhes de sua configuração. Ver:
- Otimize a consulta GROUP BY para recuperar a última linha por usuário