Folha de consulta de SQL (PostgreSQL)
As instruções de que você mais precisa, com um exemplo de cada. Os exemplos rodam no banco de dados de prática da padaria e usam a sintaxe do PostgreSQL. Outros bancos diferem em pequenos detalhes, que são indicados onde importam.
Ler e filtrar
SELECT escolhe as colunas, FROM indica a tabela, WHERE mantém as linhas que correspondem, ORDER BY ordena e LIMIT corta o resultado. Texto vai entre aspas simples.
Comentários são ignorados: `--` até o fim da linha, ou `/* ... */` em várias linhas. Use-os para explicar uma consulta, não no lugar de uma instrução clara.
SELECT name, unit_price FROM products WHERE category = 'pastry' AND unit_price < 3 ORDER BY unit_price DESC LIMIT 5;
Resultado: Os produtos de pastelaria abaixo de 3.00, do mais caro para o mais barato.
Padrões, listas, intervalos e NULL
LIKE compara padrões (% é qualquer texto, _ é um caractere; ILIKE ignora maiúsculas e minúsculas). IN testa uma lista, BETWEEN testa um intervalo inclusivo, IS NULL encontra valores ausentes.
SELECT first_name, loyalty_tier FROM customers WHERE first_name LIKE 'A%' OR loyalty_tier IS NULL ORDER BY first_name;
Resultado: Clientes cujo nome começa com A, ou que não têm nível de fidelidade.
Resumir com GROUP BY
COUNT, SUM, AVG, MIN e MAX transformam linhas em um valor por grupo. WHERE filtra as linhas antes do agrupamento, HAVING filtra os grupos.
SELECT channel, COUNT(*) AS orders FROM orders GROUP BY channel HAVING COUNT(*) > 5 ORDER BY channel;
Resultado: Só o canal online, com 7 pedidos.
Juntar tabelas
INNER JOIN mantém as correspondências, LEFT JOIN mantém cada linha da tabela da esquerda. Dê apelidos curtos às tabelas e sempre faça a junção pela chave.
SELECT p.name, SUM(oi.quantity) AS units FROM products AS p JOIN order_items AS oi ON oi.product_id = p.product_id GROUP BY p.name ORDER BY units DESC, p.name LIMIT 3;
Resultado: Os três produtos mais vendidos.
CASE: if/else em SQL
CASE retorna o valor da primeira condição verdadeira, como SES no Excel. Sem ELSE, ele retorna NULL.
SELECT name,
CASE WHEN unit_price < 3 THEN 'budget' WHEN unit_price <= 4 THEN 'standard' ELSE 'premium' END AS band
FROM products
ORDER BY product_id;Resultado: Cada produto rotulado como budget, standard ou premium.
Subconsultas e WITH
Uma subconsulta é uma consulta dentro de outra. WITH dá um nome a uma delas, para que você leia a consulta principal como uma história.
ANY e ALL comparam um valor com uma subconsulta inteira: `> ALL` significa maior que cada valor, `> ANY` maior que pelo menos um. `= ANY` é o mesmo que IN.
WITH spend AS ( SELECT o.customer_id, SUM(oi.quantity * p.unit_price) AS total FROM orders AS o JOIN order_items AS oi ON oi.order_id = o.order_id JOIN products AS p ON p.product_id = oi.product_id GROUP BY o.customer_id ) SELECT customer_id, total FROM spend WHERE total > 30 ORDER BY total DESC;
Resultado: Cliente 1 (Lopez) com 37.10 e cliente 3 (Dubois) com 36.00.
Funções de janela
OVER adiciona um cálculo entre linhas sem recolhê-las: classificações, totais acumulados, e LAG/LEAD para a linha anterior e a seguinte.
SELECT order_id, order_date,
RANK() OVER (ORDER BY order_date) AS day_rank,
LAG(order_date) OVER (ORDER BY order_id) AS prev_date
FROM orders
ORDER BY order_id;Resultado: Cada pedido com sua classificação por data e a data do pedido anterior.
Alterar dados
INSERT adiciona linhas, UPDATE altera e DELETE remove. Sempre inclua WHERE em UPDATE e DELETE, e execute primeiro como SELECT para ver o que será afetado. Envolva alterações arriscadas em BEGIN e ROLLBACK.
`INSERT INTO t SELECT ...` copia linhas para uma tabela que já existe. `CREATE TABLE t AS SELECT ...` cria uma tabela nova a partir de uma consulta. Chaves inteiras podem se preencher com `GENERATED ALWAYS AS IDENTITY` (MySQL: AUTO_INCREMENT; SQL Server: IDENTITY).
UPDATE products SET unit_price = unit_price + 0.10 WHERE category = 'drinks' RETURNING name, unit_price;
Resultado: As duas bebidas com seus novos preços.
Perguntas comuns
- Em que ordem o SQL executa uma consulta?
- FROM e JOIN, depois WHERE, GROUP BY, HAVING, SELECT, ORDER BY e por fim LIMIT. Por isso um WHERE não pode usar um apelido de coluna do SELECT, mas o ORDER BY pode.
- O SQL diferencia maiúsculas de minúsculas?
- Palavras-chave e nomes de tabelas ou colunas não (o PostgreSQL converte nomes sem aspas para minúsculas). Valores de texto sim: 'Paris' e 'paris' são diferentes, a não ser que você use ILIKE ou LOWER().
- Isso funciona no MySQL, no SQL Server ou no SQLite?
- O núcleo (SELECT, WHERE, GROUP BY, JOIN, CASE) funciona. As diferenças estão em LIMIT (TOP no SQL Server), concatenação de texto, funções de data e RETURNING. Consulte a documentação do seu banco para esses pontos.
- Como escrevo um comentário em SQL?
- Uma linha começa com -- e vai até o fim dessa linha. Um comentário de bloco começa com /* e termina com */. O banco ignora os dois. O Microsoft Access não aceita comentários.
Pratique
- Seu primeiro SELECT
- Filtrar linhas com WHERE
- Contar, somar e agrupar
- Combine tabelas com JOIN
- Decidir por condições: CASE WHEN
- Ranking e totais acumulados: funções de janela
- Adicionar, alterar e remover linhas
- Consultas dentro de consultas: subconsultas, WITH e EXISTS
- Criar uma tabela com regras: CREATE TABLE e transações