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 :-
OFILTERA cláusula em si só pode funcionar com valores da linha atual.
-
Mais importante,FILTERnã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