Introdução a Consultas com JOIN
Introdução a Consultas com JOIN
Imagine que você vai a um banco e o atendente precisa visualizar simultaneamente suas tabelas de "informações da conta" e "informações pessoais". Ele não consulta separadamente e faz a correspondência manualmente — em vez disso, ele "junta" as duas tabelas usando seu número de identificação para ver o quadro completo de uma só vez. JOIN é a mágica no SQL que permite que múltiplas tabelas "conversem" entre si.
1. Conceitos Fundamentais
Por que precisamos de JOINs?
Ao projetar um banco de dados, dividimos os dados em múltiplas tabelas para evitar redundância. Por exemplo, a tabela employees armazena apenas department_id, em vez de duplicar o nome e o endereço do departamento. Mas as consultas frequentemente precisam "remontar" as informações completas, e é aí que entram os JOINs.
-- Sem JOIN: só é possível ver department_id, não o nome do departamento
SELECT name, department_id, salary FROM employees;
-- Com JOIN: nome do funcionário e nome do departamento exibidos juntos
SELECT e.name, d.name AS department, e.salary
FROM employees e
JOIN departments d ON e.department_id = d.id;
Tipos de Relacionamento entre Tabelas
| Tipo de Relacionamento | Descrição | Exemplo |
|---|---|---|
| Um-para-Um (1:1) | Uma linha na tabela A corresponde a uma linha na tabela B | Um usuário possui um documento de identidade |
| Um-para-Muitos (1:N) | Uma linha na tabela A corresponde a múltiplas linhas na tabela B | Um departamento tem múltiplos funcionários |
| Muitos-para-Muitos (M:N) | Múltiplas linhas na tabela A correspondem a múltiplas linhas na tabela B | Alunos e disciplinas (vinculados através da tabela de matrícula) |
Em nosso banco de dados de exemplo:
departments→employees: Um-para-Muitos (um departamento tem múltiplos funcionários)products→orders: Um-para-Muitos (um produto pode aparecer em múltiplos pedidos)
Chave Estrangeira
Uma chave estrangeira é a ponte que estabelece os relacionamentos entre tabelas. É uma coluna na tabela A que referencia a chave primária da tabela B, garantindo a consistência dos dados.
-- department_id na tabela employees é uma chave estrangeira apontando para id na tabela departments
CREATE TABLE employees (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
department_id INTEGER, -- Chave estrangeira
salary DECIMAL(10,2),
hire_date DATE,
FOREIGN KEY (department_id) REFERENCES departments(id)
);
PRAGMA foreign_keys = ON; para que tenham efeito.
Sintaxe INNER JOIN
INNER JOIN retorna apenas linhas que correspondem em ambas as tabelas. Se uma linha não tiver dados correspondentes na outra tabela, ela é excluída.
SELECT nome_coluna
FROM tabela_A
INNER JOIN tabela_B ON tabela_A.coluna = tabela_B.coluna;
Condição ON
A cláusula ON especifica a condição de junção — ou seja, qual coluna é usada para correspondência entre as duas tabelas. Normalmente compara uma chave estrangeira com uma chave primária.
-- Condição ON: employees.department_id = departments.id
SELECT e.name, d.name AS department
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
Aliases de Tabela (AS)
Quando os nomes das tabelas são longos ou você precisa distinguir colunas com o mesmo nome, você pode usar AS para criar aliases para as tabelas, simplificando a escrita:
-- Sem aliases: é necessário escrever os nomes completos toda vez
SELECT employees.name, departments.name
FROM employees
INNER JOIN departments ON employees.department_id = departments.id;
-- Com aliases: mais conciso
SELECT e.name, d.name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
2. Sintaxe/Uso Básico
Sintaxe Completa do INNER JOIN
SELECT tabela_A.coluna1, tabela_A.coluna2, tabela_B.coluna1
FROM tabela_A
INNER JOIN tabela_B ON tabela_A.chave_estrangeira = tabela_B.chave_primaria
WHERE condição
ORDER BY nome_coluna;
INNER pode ser omitida — escrever apenas JOIN é equivalente a INNER JOIN.
A JOIN B ON ... JOIN C ON ....
Exemplo: Consultar Funcionários e Seus Departamentos (Dificuldade ⭐)
A necessidade mais básica — visualizar o nome do departamento ao qual cada funcionário pertence:
SELECT e.name AS funcionario, d.name AS departamento, e.salary
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;
Saída:
funcionario departamento salary
----------- ------------ --------
Zhang San Technology 15000.00
Li Si Technology 18000.00
Wang Wu Marketing 12000.00
Zhao Liu Finance 13000.00
Qian Qi Technology 20000.00
Sun Ba Marketing 11000.00
Wu Shi Finance 14000.00
Nota: Zhou Jiu não aparece porque seu department_id é NULL. O INNER JOIN mantém apenas linhas que correspondem em ambas as tabelas.
Exemplo: Consultar Detalhes de Pedidos (Junção de Três Tabelas) (Dificuldade ⭐⭐)
Em cenários reais de negócio, juntar múltiplas tabelas é comum. Consultar nome do cliente, nome do produto, preço unitário e total de cada pedido:
SELECT o.customer_name, p.name AS produto,
p.price, o.quantity,
(p.price * o.quantity) AS total
FROM orders o
INNER JOIN products p ON o.product_id = p.id
ORDER BY total DESC;
Saída:
customer_name produto price quantity total
------------- -------------- -------- -------- --------
Xiao Li iPad Air 4799.00 3 14397.00
Xiao Gang MacBook Pro 12999.00 1 12999.00
Xiao Wang iPhone 15 5999.00 2 11998.00
Xiao Ming iPhone 15 5999.00 1 5999.00
Xiao Gang iPhone 14 4999.00 1 4999.00
Xiao Hong Magic Keyboard 999.00 5 4995.00
Xiao Ming Apple Watch 2999.00 1 2999.00
Xiao Hong AirPods Pro 1899.00 2 3798.00
3. Casos de Uso Comuns
Caso 1: Consultar Todos os Funcionários do Departamento de Tecnologia
Primeiro encontrar o ID do departamento via JOIN, depois filtrar com WHERE:
SELECT e.name, e.salary, e.hire_date
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
WHERE d.name = 'Technology';
Saída:
name salary hire_date
-------- -------- ----------
Zhang San 15000.00 2023-01-15
Li Si 18000.00 2022-06-01
Qian Qi 20000.00 2020-08-05
Caso 2: Contar Funcionários por Departamento
SELECT d.name AS departamento, COUNT(e.id) AS qtd_funcionarios
FROM departments d
INNER JOIN employees e ON d.id = e.department_id
GROUP BY d.name;
Saída:
departamento qtd_funcionarios
------------ ----------------
Technology 3
Marketing 2
Finance 2
❓ Perguntas Frequentes
P: Qual tem melhor desempenho, JOIN ou subconsulta? R: Em geral, JOINs têm melhor desempenho porque os mecanismos de banco de dados possuem otimizadores especializados para JOINs. Subconsultas em alguns casos podem produzir tabelas temporárias, resultando em desempenho ligeiramente inferior. No entanto, depende do volume de dados e dos índices — use
EXPLAINpara verificar o plano de execução.
P: Qual é a diferença entre ON e WHERE? R:
ONé a condição de junção que determina como duas tabelas são pareadas;WHEREé a condição de filtro que determina quais linhas são exibidas. Eles têm efeitos semelhantes no INNER JOIN, mas diferem significativamente no LEFT JOIN —ONnão afeta a preservação da tabela da esquerda, enquantoWHEREfiltra linhas NULL.
P: Aliases de tabela são obrigatórios? R: Não são obrigatórios, mas são fortemente recomendados. Aliases de tabela tornam o SQL mais conciso, especialmente em junções de múltiplas tabelas, onde melhoram significativamente a legibilidade.
P: O que acontece se uma chave estrangeira for NULL? R: O INNER JOIN excluirá essa linha porque não há dados associados correspondentes. Se você quiser manter essas linhas, use LEFT JOIN (abordado na próxima lição).
📖 Resumo
- Bancos de dados dividem dados em tabelas para evitar redundância, e JOINs "remontam" informações completas durante as consultas
- Existem três tipos de relacionamentos entre tabelas: um-para-um, um-para-muitos e muitos-para-muitos; o mais comum é um-para-muitos
- Uma chave estrangeira é a ponte entre tabelas, referenciando a chave primária de outra tabela
- INNER JOIN retorna apenas linhas que correspondem em ambas as tabelas, usando
ONpara especificar a condição de junção - Aliases de tabela (
AS) tornam o SQL mais conciso; sempre os use em junções de múltiplas tabelas
📝 Exercícios
Exercício 1 (⭐): Escreva uma consulta para exibir o nome do cliente, nome do produto e categoria do produto para todos os pedidos (requer juntar as tabelas orders e products).
Exercício 2 (⭐⭐): Escreva uma consulta para exibir o salário médio por departamento, mostrando apenas departamentos cujo salário médio excede 12000 (dica: JOIN + GROUP BY + HAVING).
Exercício 3 (⭐⭐⭐): Escreva uma consulta para exibir o valor total gasto por cada cliente em produtos, ordenado por valor total em ordem decrescente. Mostre o nome do cliente, quantidade de pedidos e valor total.
Próxima Lição
👉 08-join-types - Tipos de Junção Explicados: Aprofunde-se em LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN, CROSS JOIN e SELF JOIN, e domine a estratégia para escolher o tipo de junção correto!



