0Pricing
SQL Interview Prep · Aula

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 BY para 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 a SUM(CASE WHEN ... THEN 1 ELSE 0 END).
  • A sintaxe de intervalos varia: PostgreSQL + INTERVAL '7 days', MySQL DATE_ADD(d, INTERVAL 7 DAY), SQL Server DATEADD(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/LAG para 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

  1. Criando um funil de várias etapas
  2. Eventos ordenados e janelas de tempo
  3. Atribuição e métricas de teste A/B
  4. Incremento, significância e proteções em SQL
← Voltar para SQL Interview Prep