Eventos ordenados e janelas de tempo
Garantindo que as etapas ocorram em sequência e dentro de um limite de tempo usando funções de janela.
Eventos ordenados e janelas de tempo é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.
Por que a ordem e o tempo são importantes
O funil básico da lição anterior verifica apenas se um usuário realizou cada etapa. Um entrevistador mais criterioso perguntará: as etapas aconteceram na ordem correta e dentro de um prazo razoável?
Um usuário que fez uma compra na segunda-feira e visitou a página de marketing na sexta-feira não converteu pelo seu funil. A sequência e o tempo transformam um funil ingênuo, baseado em indicadores, em um funil confiável.
A ideia do primeiro horário por usuário
Para analisar a ordem, registre o primeiro momento de cada usuário em cada etapa. A primeira visita, o primeiro cadastro, a primeira compra.
Então, uma conversão válida significa que first_signup_time >= first_visit_time e assim por diante na sequência. Agrupar MIN(event_time) por etapa fornece esses pontos de referência.
SELECT
user_id,
MIN(CASE WHEN event_name = 'visit' THEN event_time END) AS first_visit,
MIN(CASE WHEN event_name = 'signup' THEN event_time END) AS first_signup,
MIN(CASE WHEN event_name = 'purchase' THEN event_time END) AS first_purchase
FROM events
GROUP BY user_id;Exigindo as etapas em sequência
Com as primeiras marcas temporais de cada etapa, garantir a ordem é uma questão de comparação. Um usuário realmente converteu para a etapa 3 somente se cada marca temporal não for NULL e aumentar de forma monotônica.
Observe como uma marca temporal NULL (quando a etapa nunca aconteceu) falha naturalmente na comparação, exatamente como você deseja.
WITH t AS (
SELECT user_id,
MIN(CASE WHEN event_name='visit' THEN event_time END) AS visit_t,
MIN(CASE WHEN event_name='signup' THEN event_time END) AS signup_t,
MIN(CASE WHEN event_name='purchase' THEN event_time END) AS purchase_t
FROM events GROUP BY user_id
)
SELECT COUNT(*) AS converted_in_order
FROM t
WHERE visit_t IS NOT NULL
AND signup_t >= visit_t
AND purchase_t >= signup_t;Adicionando um intervalo de tempo
A maioria dos funis tem um prazo: "converta em até 7 dias após a primeira visita". Adicione um limite de intervalo entre a primeira etapa e a etapa final.
A aritmética de datas varia conforme o dialeto. No PostgreSQL, você pode escrever visit_t + INTERVAL '7 days'; no MySQL, use DATE_ADD(visit_t, INTERVAL 7 DAY). Sempre informe qual é o seu dialeto.
WITH t AS (
SELECT user_id,
MIN(CASE WHEN event_name='visit' THEN event_time END) AS visit_t,
MIN(CASE WHEN event_name='purchase' THEN event_time END) AS purchase_t
FROM events GROUP BY user_id
)
SELECT COUNT(*) AS purchased_within_7d
FROM t
WHERE purchase_t >= visit_t
AND purchase_t < visit_t + INTERVAL '7 days';Por que usar a primeira marca temporal, e não qualquer uma
Uma questão sutil de entrevista: o intervalo deve começar na primeira visita do usuário ou na visita mais recente antes do cadastro? Isso depende da pergunta sobre o produto.
- Intervalos de primeiro contato medem quanto tempo decorre do interesse inicial até a conversão.
- Intervalos de último contato medem a aceleração da conversão após a visita final.
Pergunte ao entrevistador a qual opção ele se refere; escolher deliberadamente demonstra senioridade.
Eventos ordenados com LEAD
Para caminhos complexos com várias etapas, as funções de janela são excelentes. Ordene os eventos de cada usuário por horário e use LEAD para consultar o evento seguinte e confirmar que ele é a próxima etapa esperada.
Isso funciona para caminhos em que as etapas se alternam com eventos não relacionados.
SELECT
user_id,
event_name,
event_time,
LEAD(event_name) OVER (PARTITION BY user_id ORDER BY event_time) AS next_event,
LEAD(event_time) OVER (PARTITION BY user_id ORDER BY event_time) AS next_time
FROM events;Correspondendo à próxima etapa esperada
Parta de LEAD: mantenha as linhas em que uma 'visita' é imediatamente seguida por um 'cadastro'. Isso encontra transições realmente sequenciais, e não apenas uma ocorrência conjunta.
Você pode encadear essas verificações de transição para validar um caminho ordenado completo, etapa por etapa.
WITH seq AS (
SELECT user_id, event_name, event_time,
LEAD(event_name) OVER (PARTITION BY user_id ORDER BY event_time) AS next_event
FROM events
)
SELECT COUNT(DISTINCT user_id) AS visit_then_signup
FROM seq
WHERE event_name = 'visit' AND next_event = 'signup';Tempo entre etapas consecutivas
Os entrevistadores adoram perguntar: "quanto tempo cada etapa leva?" Use LEAD na marca temporal e faça a subtração. A diferença entre eventos consecutivos é o tempo de permanência naquela etapa.
Calcule a mediana ou a média por transição para encontrar a etapa mais lenta do funil.
WITH seq AS (
SELECT user_id, event_name, event_time,
LEAD(event_time) OVER (PARTITION BY user_id ORDER BY event_time) AS next_time
FROM events
)
SELECT
event_name,
AVG(EXTRACT(EPOCH FROM (next_time - event_time)) / 3600.0) AS avg_hours_to_next
FROM seq
WHERE next_time IS NOT NULL
GROUP BY event_name;O caso de borda de marcas temporais idênticas
E se dois eventos tiverem exatamente o mesmo event_time? Nesse caso, signup_t >= visit_t será verdadeiro mesmo que ocorram simultaneamente, e a ordenação apenas pelo horário será ambígua.
- Use
>=ou>deliberadamente e explique o motivo. - Adicione um critério de desempate, como um identificador de sequência do evento, a
ORDER BYpara tornar as janelas determinísticas.
Mencionar isso sem que ninguém peça impressiona os entrevistadores.
SELECT user_id, event_name,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY event_time, event_id) AS step_seq
FROM events;Combinando ordem e intervalo em uma única consulta
Aqui está o funil completo, em ordem e dentro do intervalo. Ele usa a primeira visita como referência, exige que a primeira ocorrência de cada etapa posterior aconteça depois da anterior e limita todo o caminho a 7 dias.
Essa é a resposta que diferencia um candidato que entende de funis de alguém que apenas conta indicadores.
WITH t AS (
SELECT user_id,
MIN(CASE WHEN event_name='visit' THEN event_time END) AS v,
MIN(CASE WHEN event_name='signup' THEN event_time END) AS s,
MIN(CASE WHEN event_name='purchase' THEN event_time END) AS p
FROM events GROUP BY user_id
)
SELECT
COUNT(*) FILTER (WHERE v IS NOT NULL) AS visited,
COUNT(*) FILTER (WHERE s >= v AND s < v + INTERVAL '7 days') AS signed_up,
COUNT(*) FILTER (WHERE s >= v AND p >= s AND p < v + INTERVAL '7 days') AS purchased
FROM t;Observações sobre diferentes dialetos
Duas lembranças sobre portabilidade durante a programação ao vivo:
FILTER (WHERE ...)em agregações faz parte do SQL padrão e funciona no PostgreSQL; no MySQL ou em mecanismos mais antigos, recorra aSUM(CASE WHEN ... THEN 1 ELSE 0 END).- A sintaxe de intervalos varia: PostgreSQL
+ INTERVAL '7 days', MySQLDATE_ADD(d, INTERVAL 7 DAY), SQL ServerDATEADD(day, 7, d).
Declare sua suposição, e o entrevistador raramente se importará com o dialeto escolhido; o importante é saber que eles diferem.
Verificação rápida
Você precisa contar os usuários que concluíram visita -> cadastro -> compra nessa ordem, dentro de 7 dias da primeira visita. Qual abordagem está correta?
Recapitulação: Eventos ordenados e janelas de tempo
Principais conclusões:
- Capture o primeiro registro de data e hora de cada etapa de cada usuário com
MIN(CASE ...). - Imponha a sequência exigindo que o horário de cada etapa seja igual ou posterior ao da etapa anterior.
- Limite o caminho com um intervalo, informando a sintaxe do seu dialeto.
- Use
LEAD/LAGpara verificar transições e o tempo de permanência entre etapas. - Trate empates no mesmo registro de data e hora com um critério de desempate em
ORDER BY.
A seguir: passando de funis para experimentos e calculando métricas por variante.
Perguntas Frequentes
A aula “Eventos ordenados e janelas de tempo” é grátis?
Sim — o texto completo de “Eventos ordenados e janelas de tempo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.
O que vou aprender em “Eventos ordenados e janelas de tempo”?
Garantindo que as etapas ocorram em sequência e dentro de um limite de tempo usando funções de janela. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Interview Prep?
Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Eventos ordenados e janelas de tempo”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Interview Prep?
Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Criando um funil de várias etapas
- Eventos ordenados e janelas de tempo
- Atribuição e métricas de teste A/B
- Incremento, significância e proteções em SQL