12.1 Introdução ao JOIN
O JOIN no SQL é uma operação que permite combinar dados de duas ou mais tabelas em uma única consulta SELECT, baseando-se em colunas relacionadas entre elas.
12.1.1 Estrutura de Tabelas Relacionais
Em bancos de dados relacionais, os dados são frequentemente normalizados em múltiplas tabelas para melhorar a escalabilidade e reduzir a redundância. Cada tabela armazena informações específicas, e as relações entre elas são estabelecidas através de chaves comuns.
12.1.2 Motivação para Usar JOINs
Utilizar JOINs permite recuperar informações de várias tabelas em uma única operação, simplificando consultas complexas. Os JOINs são construídos dinamicamente pelo SGBD durante a execução da consulta, o que significa que não são entidades físicas no banco de dados.
É importante notar que o uso excessivo de JOINs pode impactar o desempenho, pois operações de junção são computacionalmante intensivas. Muitos SGBDs impõem limites no número de tabelas que podem ser unidas simultaneamente.
12.2 Implementando JOINs
Para evitar ambiguidades ao consultar colunas de múltiplas tabelas, recomenda-se utilizar nomes de colunas totalmente qualificados (nome_tabela.coluna). A cláusula WHERE é essencial para definir as condições de junção e evitar resultados indesejados.
-- Exemplo de estrutura de tabelas
SELECT * FROM Suppliers;
+------------+-------------------+------------------+-----------+--------+
| supplier_id | supplier_name | supplier_address | city | country|
+------------+-------------------+------------------+-----------+--------+
| SUP01 | Tech Supplies | 123 Elm Street | Porto | PT |
| SUP02 | Global Parts | 456 Oak Avenue | Lisboa | PT |
+------------+-------------------+------------------+-----------+--------+
SELECT * FROM Items;
+---------+------------+---------------+-----------+
| item_id | supplier_id| item_name | unit_price|
+---------+------------+---------------+-----------+
| ITM01 | SUP01 | Widget Alpha | 12.50 |
| ITM02 | SUP01 | Widget Beta | 15.75 |
| ITM03 | SUP02 | Gadget X | 8.99 |
+---------+------------+---------------+-----------+
-- Consulta com JOIN usando WHERE
SELECT supplier_name, item_name, unit_price
FROM Suppliers, Items
WHERE Suppliers.supplier_id = Items.supplier_id;
12.2.1 Importância da Cláusula WHERE
Em junções sem uma condição adequada, o resultado é um produto cartesiano, onde cada linha da primeira tabela é combinada com todas as linhas da segunda. Isso pode gerar um grande volume de dados irrelevantes. Por exemplo:
-- Produto cartesiano (evitar)
SELECT supplier_name, item_name, unit_price FROM Suppliers, Items;
12.2.2 Junção Interna (INNER JOIN)
A junção mais comum é a junção interna, que retorna apenas as linhas onde há correspondência nas colunas especificadas. A sintaxe recomendada pelo SQL padrão utiliza INNER JOIN com a cláusula ON.
-- Usando INNER JOIN
SELECT supplier_name, item_name, unit_price
FROM Suppliers
INNER JOIN Items ON Suppliers.supplier_id = Items.supplier_id;
12.2.3 Unindo Múltiplas Tabelas
É possível unir mais de duas tabelas, definindo todas as condições de relação na cláusula WHERE ou usando múltiplos JOINs. Considere um cenário com uma tabela de pedidos:
-- Tabela de detalhes do pedido
SELECT * FROM OrderDetails;
+-----------+---------+----------+-------------+
| order_id | item_id | quantity | total_price |
+-----------+---------+----------+-------------+
| ORD1001 | ITM01 | 10 | 125.00 |
| ORD1001 | ITM03 | 5 | 44.95 |
| ORD1002 | ITM02 | 20 | 315.00 |
+-----------+---------+----------+-------------+
-- Consulta unindo três tabelas
SELECT item_name, supplier_name, unit_price, quantity
FROM OrderDetails, Items, Suppliers
WHERE Items.supplier_id = Suppliers.supplier_id
AND OrderDetails.item_id = Items.item_id
AND order_id = 'ORD1001';
Para substituir subconsultas por JOINs, considere esta transformação:
-- Versão com subconsulta
SELECT client_name, client_contact
FROM Clients
WHERE client_id IN (
SELECT client_id
FROM SalesOrders
WHERE order_id IN (
SELECT order_id
FROM OrderDetails
WHERE item_id = 'ITM03'
)
);
-- Versão equivalente com JOIN
SELECT client_name, client_contact
FROM Clients, SalesOrders, OrderDetails
WHERE Clients.client_id = SalesOrders.client_id
AND OrderDetails.order_id = SalesOrders.order_id
AND item_id = 'ITM03';