Vamos falar sobre entrevistas (parte 2) 😎

No post anterior, abordamos soft skills, a metodologia STAR e Excel. Isso é o básico. Agora vamos mais longe, SQL.

Se você domina bem o Excel, já entende os fundamentos: como os dados se relacionam, quais problemas ocorrem nas junções, como funcionam as agregações. A transição para o SQL no início são basicamente 5 comandos: SELECT, FROM, WHERE, JOIN, GROUP BY. Funções de janela e tabelas temporárias são úteis, mas no início não são críticas.

Agora, ao principal. O problema principal não é a sintaxe. O problema está nos blocos que não derrubam a consulta. O código executa, o interpretador fica em silêncio, mas o resultado não é o que o entrevistador espera. É nisso que muitos falham.

1️⃣NOT IN + NULL: silêncio em vez de dados

Em SQL: NULL ≠ vazio ≠ 0. Quem estudou Python sabe: zero é zero, NULL é vazio, nada. Tenha isso em mente.

Problema: encontrar usuários que não estão na lista negra.


SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM blocked)

Parece correto. Mas se em blocked houver pelo menos uma linha com user_id = NULL, o resultado: 0 linhas. O SQL não consegue comparar com NULL e retorna silenciosamente vazio.


SELECT * FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM blocked b
WHERE b.user_id = u.id
)

A propósito, NOT EXISTS também é mais rápido: pega o id, vai para a segunda tabela, encontra a primeira ocorrência, para. NOT IN varre a tabela inteira de cima a baixo. Em tabelas grandes, a diferença é perceptível.

2️⃣ LEFT JOIN que silenciosamente se tornou INNER JOIN

Os tipos de JOIN serão detalhados em posts futuros da série. Agora, apenas a essência da armadilha.

SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.status = 'completed'

O que acontece: WHERE elimina as linhas NULL da tabela direita. Clientes sem pedidos simplesmente desaparecem. LEFT JOIN se transforma em INNER JOIN. E o resultado errado.

SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o
ON c.id = o.customer_id
AND o.status = 'completed'

Uma linha com AND. A diferença é fundamental.

3️⃣AVG mente bonito

Aqui vai um problema. 10 linhas de vendas. Três têm NULL. Quanto AVG retorna? A média dos 7, não dos 10. Se os valores parecem plausíveis, é difícil notar o truque. O número é realista, mas distorcido.

SELECT AVG(salary) FROM employees



SELECT AVG(COALESCE(salary, 0)) FROM employees

COALESCE: encontrou NULL, substituiu por 0. Pode ser sem ele, mas então explique ao entrevistador que você entende o comportamento do AVG e o aceita conscientemente. Ambas as opções são válidas 👌

4️⃣Ordem de execução: a principal armadilha

Escrevemos: SELECT → FROM → WHERE → GROUP BY.
Executa: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.

Ilógico? Pois é 🤷‍♀️


SELECT category, AVG(sales) AS avg_sales
FROM orders
WHERE avg_sales > 1000
GROUP BY category

O alias avg_sales ainda não existe na etapa WHERE. O sistema simplesmente não conhece esse campo.


SELECT category, AVG(sales) AS avg_sales
FROM orders
GROUP BY category
HAVING AVG(sales) > 1000

HAVING é a filtragem após a agregação. Detalharemos em um post separado da série.

5️⃣Esqueceu a sintaxe? Não entre em pânico

Acontece: nervosismo, faz tempo que não mexe no assunto. Bem, quem nunca. Diga diretamente: "Entendo a lógica, posso descrever os passos. A sintaxe exata eu pesquisaria no Google". Qualquer profissional razoável vai valorizar isso. Entender a lógica é uma coisa. Pesquisar uma função = 30 segundos.

Bônus no final: a primeira pergunta em um teste = "Qual é o seu SGBD?".
DATE_TRUNC — PostgreSQL. DATE_FORMAT — MySQL. A consulta correta para o banco errado = erro à toa.

No próximo post SQL: Retenção e coortes. E amanhã, post e artigo sobre o caso da minha equipe com a empresa Grand-Alpha. Eles trabalham com ração animal.

Pergunta para vocês. Já aconteceu de esquecer a resposta e, por mais que tentasse, não lembrar? Como agiu nessa situação? 👇

#sql
@data_dzen