Perguntas de entrevista de SQL, com respostas que você pode executar
A maioria das entrevistas de SQL repete as mesmas dez ou doze ideias. A seguir estão as mais comuns, com uma resposta curta e uma consulta que funciona no PostgreSQL. Os exemplos usam um pequeno banco de dados de padaria (customers, products, orders e order_items), para que você possa testar cada um em uma lição deste site.
Encontre o segundo maior valor
Uma resposta simples é ordenar em ordem decrescente e pular a primeira linha. Ela retorna uma única linha, mesmo que várias linhas tenham o segundo preço.
Se os empates importarem, calcule a classificação com DENSE_RANK e fique com a classificação 2. DENSE_RANK não deixa lacunas depois dos empates, então a classificação 2 é sempre o segundo valor distinto.
SELECT name, unit_price FROM ( SELECT name, unit_price, DENSE_RANK() OVER (ORDER BY unit_price DESC) AS r FROM products ) AS ranked WHERE r = 2;
Resultado: A fatia de Chocolate cake, por 4.20.
Encontre duplicatas
Agrupe pela coluna que deveria ser única e mantenha os grupos que têm mais de uma linha.
SELECT order_date, COUNT(*) AS orders FROM orders GROUP BY order_date HAVING COUNT(*) > 1 ORDER BY order_date;
Resultado: Três datas, cada uma com dois pedidos: 1, 2 e 6 de setembro.
Encontre linhas sem correspondência
Use um LEFT JOIN e mantenha as linhas em que o lado direito é NULL, ou use NOT EXISTS. As duas respostas dizem “quais clientes nunca fizeram pedido?”.
Evite NOT IN com uma subconsulta que pode retornar NULL: um único NULL torna toda a condição desconhecida e você não recebe nenhuma linha.
SELECT c.first_name, c.last_name FROM customers AS c LEFT JOIN orders AS o ON o.customer_id = c.customer_id WHERE o.order_id IS NULL ORDER BY c.customer_id;
Resultado: Grace Kim e Hugo Meyer.
Linha principal de cada grupo
Classifique dentro de cada grupo com PARTITION BY e depois mantenha a classificação 1 em uma consulta externa. Use RANK para manter os empates, ou ROW_NUMBER para manter exatamente uma linha por grupo.
SELECT category, name, units
FROM (
SELECT p.category, p.name, SUM(oi.quantity) AS units,
RANK() OVER (PARTITION BY p.category ORDER BY SUM(oi.quantity) DESC) AS rk
FROM products AS p
JOIN order_items AS oi ON oi.product_id = p.product_id
GROUP BY p.category, p.name
) AS ranked
WHERE rk = 1
ORDER BY category, name;Resultado: O item mais vendido de cada categoria. Cake aparece duas vezes porque empata em 3 unidades.
Total acumulado
Use SUM como função de janela com ORDER BY. Ordene por uma coluna sem empates, senão as linhas que empatam são somadas juntas.
SELECT order_id,
SUM(quantity) AS units,
SUM(SUM(quantity)) OVER (ORDER BY order_id) AS running_units
FROM order_items
GROUP BY order_id
ORDER BY order_id;Resultado: Unidades por pedido e o total até ali, terminando em 56.
WHERE versus HAVING
WHERE filtra as linhas antes de agrupá-las, por isso não pode usar uma função de agregação. HAVING filtra os grupos depois da agregação. No exemplo, WHERE remove primeiro os produtos baratos, e HAVING mantém as categorias com pelo menos dois dos produtos restantes.
SELECT category, COUNT(*) AS products FROM products WHERE unit_price > 2.50 GROUP BY category HAVING COUNT(*) >= 2 ORDER BY category;
Resultado: Bread e cake, com dois produtos cada acima de 2.50. Pastry e drinks têm só um produto acima de 2.50 e ficam de fora.
UNION versus UNION ALL
UNION remove linhas duplicadas, o que exige trabalho extra. UNION ALL mantém tudo e é mais rápido. Use UNION ALL, a não ser que você precise remover as duplicatas.
SELECT city FROM customers UNION SELECT city FROM customers ORDER BY city;
Resultado: Cinco cidades, cada uma uma vez. Com UNION ALL haveria 16 linhas.
Perguntas comuns
- Qual é a diferença entre DELETE, TRUNCATE e DROP?
- DELETE remove as linhas que você escolher (WHERE) e pode ser desfeito com rollback. TRUNCATE esvazia a tabela inteira rapidamente e mantém a estrutura. DROP remove a própria tabela, com sua estrutura e seus dados.
- Qual é a diferença entre INNER JOIN e LEFT JOIN?
- INNER JOIN mantém apenas as linhas que têm correspondência nos dois lados. LEFT JOIN mantém todas as linhas da tabela da esquerda e preenche o lado direito com NULL onde não há correspondência.
- Qual é a diferença entre RANK, DENSE_RANK e ROW_NUMBER?
- Os três numeram as linhas de uma ordem. RANK dá o mesmo número aos empates e pula os números seguintes. DENSE_RANK dá o mesmo número aos empates e não pula. ROW_NUMBER nunca repete um número.
- Qual dialeto de SQL essas respostas usam?
- PostgreSQL. LIMIT/OFFSET, funções de janela, CTEs e junções funcionam quase em todos. No SQL Server use TOP ou OFFSET FETCH no lugar de LIMIT, e no Oracle use FETCH FIRST.