Grátiscode
  • Claude
  • ChatGPT

SQL a partir da pergunta de negócio

  • 4,7 (6)
  • 7
  • 5
  • 14 de jul. de 2026

Explicita as decisões escondidas antes de escrever a consulta.

Grátis

Grátis. Precisa de conta.

Laboratório

Teste o funcionamento antes de comprar.

Testar

Prompt

32 linhas

## Pergunta de negócio
{{pergunta}}

## Esquema disponível
```sql
{{esquema}}
```

Dialeto: {{dialeto}}

## Etapa 1, decisões escondidas (antes de qualquer SQL)
Liste toda decisão que a pergunta deixa em aberto e que muda o resultado. Típicas:
- Qual data conta: criação, pagamento, competência?
- Fuso horário e onde vira o dia
- O que fazer com registro cancelado, estornado, de teste ou duplicado
- Se o denominador inclui quem entrou no meio do período
- Se valor é bruto ou líquido de imposto e desconto

Para cada decisão: as opções, e qual você escolheu como padrão e por quê.

## Etapa 2, a consulta
SQL comentado, com cada decisão da etapa 1 marcada no ponto onde foi aplicada.
- CTEs nomeadas por significado de negócio, não `t1`, `t2`
- Sem `SELECT *`
- Filtros de data explícitos e inclusivos/exclusivos declarados

## Etapa 3, como conferir
Duas checagens rápidas que provam que o resultado não é absurdo (ordem de grandeza,
total que bate com outra fonte, linha conhecida).

## Etapa 4, armadilhas deste esquema
O que neste esquema específico costuma produzir número errado.

O que este prompt faz

Traduz uma pergunta ambígua de negócio em SQL, listando primeiro as decisões que o analista teria que tomar no caminho, qual data conta, o que é usuário ativo, como tratar cancelamento. A consulta vem depois, com as escolhas comentadas.

Preview

Resultado

Etapa 1, decisões escondidas

1. O que é "ativo"? Teve sessão? Tem assinatura ativa? Ambos?
Escolhi: teve ao menos uma sessão no período. É a definição de uso, e o esquema tem sessions. Se o time quiser "ativo = pagante", a consulta é outra, e o número será bem menor.

2. Sessão de qualquer duração conta? Uma sessão de 2 segundos é provavelmente um bot ou um toque acidental.
Escolhi: duração ≥ 10s. É arbitrário e você deve calibrar, mas não filtrar nada infla o número.

3. Fuso horário. started_at está em UTC ou local? Junho em UTC ≠ junho em São Paulo.
Escolhi: converto para America/Sao_Paulo. Se a coluna já estiver em horário local, remova a conversão, aplicá-la duas vezes desloca 3 horas de dados nas bordas do mês.

4. Usuário deletado no meio do mês. Ele usou o produto em junho e saiu no dia 20.
Escolhi: conta. Ele foi ativo em junho; o deleted_at posterior não apaga isso. Filtrar por deleted_at IS NULL é o erro mais comum aqui e subestima meses passados de forma crescente.

5. Usuários de teste. is_test existe, então alguém já foi mordido por isso.
Escolhi: excluir.

6. Borda do período. 30 de junho às 23h59 conta?
Escolhi: intervalo semiaberto >= 01/06 AND < 01/07. Evita o buraco de um segundo que BETWEEN com data cria.

Etapa 2, a consulta

WITH sessoes_do_periodo AS (
  SELECT
    s.user_id,
    s.id AS session_id
  FROM sessions AS s
  WHERE
    -- decisão 3 e 6: fuso local, intervalo semiaberto
    (s.started_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo')
      >= DATE '2026-06-01'
    AND (s.started_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo')
      < DATE '2026-07-01'
    -- decisão 2: descarta toque acidental e bot
    AND s.duration_s >= 10
),

usuarios_validos AS (
  SELECT u.id
  FROM users AS u
  -- decisão 5: fora os usuários de teste
  WHERE u.is_test = FALSE
  -- decisão 4: NÃO filtramos deleted_at de propósito.
  -- Quem usou em junho foi ativo em junho, mesmo que tenha saído depois.
)

SELECT COUNT(DISTINCT s.user_id) AS usuarios_ativos
FROM sessoes_do_periodo AS s
INNER JOIN usuarios_validos AS u ON u.id = s.user_id;

Etapa 3, como conferir

  1. Ordem de grandeza: rode a mesma consulta para maio e para julho. Um salto acima de 30% entre meses consecutivos quase sempre é erro de consulta, não crescimento real.
  2. Teto lógico: o resultado tem que ser menor que COUNT(*) FROM users WHERE is_test = FALSE AND created_at < '2026-07-01'. Se for maior, há duplicata em sessions.user_id apontando para usuário inexistente, sinal de FK ausente.

Etapa 4, armadilhas deste esquema

  • subscriptions.status não tem histórico. Só existe o estado atual. Você não consegue responder "quantos estavam pagantes em junho" com este esquema, só "quantos estão pagantes hoje e eram usuários em junho". São coisas diferentes, e a segunda não serve para série temporal. Precisa de uma tabela de eventos de assinatura.
  • canceled_at sem started_at da assinatura. Não dá para calcular tempo de vida.
  • Sem índice aparente em sessions.started_at. Em tabela grande, a conversão de fuso dentro do WHERE impede uso de índice. Se demorar, calcule os limites em UTC do lado de fora e compare direto com started_at.

Como usar

  1. 1

    Copie o template

    Use o botão de copiar no bloco acima. São 32 linhas de instrução.

  2. 2

    Preencha as variáveis

    Troque as 3 variáveis destacadas pelo seu conteúdo. Deixar em branco degrada a saída.

  3. 3

    Escolha um dos modelos listados

    Rode em um dos modelos listados na lateral. Modelo menor costuma degradar o resultado.

  4. 4

    Cole e execute

    Ou use o laboratório, com sua chave, e compare com o preview.