Existe um erro em SQL que nao costuma quebrar a query, mas quebra o raciocinio: misturar AND e OR sem parenteses.
O problema e traiçoeiro porque o resultado muitas vezes parece plausivel. Nao vem mensagem de erro. Nao vem alerta do banco. So vem um conjunto de linhas diferente do que voce queria.
A regra que o banco segue
No SQL, AND tem precedencia sobre OR.
Isso significa que:
WHERE status = 'rejeitado'
OR status = 'pendente'
AND valor > 200
nao e lido do jeito que muita gente imagina.
O banco interpreta assim:
WHERE status = 'rejeitado'
OR (status = 'pendente' AND valor > 200)
Nao assim:
WHERE (status = 'rejeitado' OR status = 'pendente')
AND valor > 200
E essas duas coisas podem gerar resultados bem diferentes.
O bug silencioso
Imagine que voce queria encontrar pedidos rejeitados ou pendentes acima de 200.
Se esquecer os parenteses, todos os rejeitados entram, independentemente do valor. O filtro de valor > 200 passa a valer apenas para os pendentes.
Pronto. Sua analise mudou sem fazer barulho.
Por que esse erro e tao comum
Porque a frase em portugues parece simples:
“Quero rejeitados ou pendentes acima de 200.”
O cerebro humano costuma agrupar isso intuitivamente de um jeito. O SQL agrupa de outro, com base na precedencia.
Sem parenteses, a query passa a refletir a regra do banco, nao necessariamente a regra de negocio.
O jeito seguro
Sempre que AND e OR aparecerem juntos, escreva parenteses para deixar sua intencao explicita.
SELECT id, status, valor
FROM pedidos
WHERE (status = 'rejeitado' OR status = 'pendente')
AND valor > 200;
Mesmo quando voce “acha” que esta obvio, use parenteses. SQL claro ganha de SQL esperto.
Como validar se a logica esta certa
Quando houver duvida, faca tres coisas:
1. Quebre a regra em partes
Rode um filtro so para rejeitado, outro so para pendente, e depois compare com o resultado conjunto.
2. Pegue um recorte pequeno
Escolha poucos IDs e veja manualmente quais deveriam entrar.
3. Escreva a condicao em portugues claro
Se a frase de negocio for:
“Quero clientes do plano A ou do plano B que estejam ativos”
entao a query precisa refletir exatamente isso:
WHERE (plano = 'A' OR plano = 'B')
AND status = 'ativo'
Onde isso costuma doer mais
Esse bug aparece muito em:
- funis de CRM;
- segmentacoes de marketing;
- bases de pedidos e pagamentos;
- classificacoes de risco;
- regras de campanhas e cohorts.
Ou seja: justamente em contextos onde pequenas distorcoes podem virar decisao errada.
A senioridade esta na clareza
Muita gente acha que escrever SQL bem e usar funcoes avancadas. Nao so.
Escrever SQL bem tambem e evitar ambiguidades que o proximo leitor talvez nao perceba. Parenteses aqui sao menos sobre sintaxe e mais sobre responsabilidade.
Se a query for importante o suficiente para virar numero em reuniao, ela precisa ser explicita o bastante para nao depender da interpretacao de quem le.
Resumo direto
AND vem antes de OR no SQL. Quando voce mistura os dois sem parenteses, a consulta pode fazer outra coisa sem dizer isso em voz alta.
O antídoto e simples: se a regra mistura condicoes, use parenteses sempre.
Melhor uma query um pouco mais verbosa do que uma analise errada com cara de certa.
