TOP

Lição SQL 11. Combinação avançada de tabelas (OUTER JOIN)

Na seção anterior, consideramos as maneiras mais simples de combinar tabelas - usando sentenças WHERE e INNER JOIN. Essas combinações são chamadas de combinações internas ou combinações de equivalência. Porém, o SQL tem em seu arsenal muito mais opções de união de tabelas, ou seja, existem também outros tipos de junções: junções externas, junções naturais e auto-junções. Mas primeiro vamos considerar como podemos atribuir aliases às tabelas, pois posteriormente seremos obrigados a usar nomes completos de campos (Tabela.Campo), que sem abreviaturas serão muito difíceis de operar devido ao seu grande comprimento.


1. Uso de aliases de tabela (Aliases)

Na seção anterior, aprendemos como os aliases podem ser usados para fazer referência a campos de tabela específicos ou campos calculados. SQL também nos permite usar aliases em vez de nomes de tabelas. Isso nos dá vantagens como sintaxe SQL mais curta e nos permite usar a mesma tabela várias vezes na instrução SELECT.

Run SQLSELECT Seller_name, SUM(Amount) AS Sum1 
FROM Sellers AS S, Sumproduct AS SP 
WHERE S.City = SP.City 
GROUP BY Seller_name

Exibimos a quantidade total de produtos vendidos para cada vendedor. Em nossa consulta SQL, usamos os seguintes aliases: para o campo calculado SUM(Amount) o alias Sum1, para a tabela Sellers o alias S e para Sumproduct o alias SP. Observe que os aliases de tabela também podem ser usados em outras frases, como ORDER BY, GROUP BY e outras.

2. Autoconexão (SELF JOIN)

Vamos considerar um exemplo. Suponha que precisemos saber o endereço dos vendedores que negociam no mesmo país que John Smith. Para fazer isso, criaremos a seguinte solicitação:

Run SQLSELECT Address, City, Country, Seller_name
FROM Sellers
WHERE Country = (SELECT Country 
                 FROM Sellers 
                 WHERE Seller_name = 'John Smith')

Além disso, podemos resolver esse problema por meio da autoconexão, escrevendo o seguinte código:

Run SQLSELECT S1.Address, S1.City, S1.Country, S1.Seller_name
FROM Sellers AS S1, Sellers AS S2 
WHERE S1.Country = S2.Country AND S2.Seller_name = 'John Smith'

Pseudônimos foram usados para resolver esse problema. Na primeira vez, a tabela Sellers recebeu o alias S1, na segunda vez - o alias S2. Esses aliases podem então ser usados como nomes de tabelas. No operador WHERE, adicionamos o prefixo S1 ao nome de cada campo, para que o SGBD entenda os campos de qual tabela deve ser saída (já que fizemos duas tabelas virtuais de uma tabela). A cláusula WHERE primeiro une as tabelas e depois filtra os dados da segunda tabela pelo campo Seller_name para retornar apenas os valores necessários.

As autojunções costumam ser usadas para substituir subconsultas que selecionam dados da mesma tabela que o operador externo SELECT. Embora o resultado final seja o mesmo, muitos processos de SGBDs se juntam muito mais rápido do que subconsultas. Vale a pena experimentar para determinar qual consulta funciona mais rápido.

3. Combinação natural

Uma junção natural é uma junção na qual você seleciona apenas as colunas que não se repetem. Isso geralmente é feito escrevendo (SELECT *) para uma tabela e especificando uma lista de campos para o restante das tabelas. Exemplo:

Run SQLSELECT SP.*, S.Country
FROM Sumproduct AS SP, Sellers AS S 
WHERE SP.City = S.City

Neste exemplo, o curinga (*) é usado apenas para a primeira tabela. Todas as outras colunas são especificadas explicitamente, portanto colunas duplicadas não são selecionadas.

4. Combinação externa (OUTER JOIN)

Normalmente, ao mesclar, as linhas de uma tabela são vinculadas às linhas correspondentes de outra tabela, porém, em alguns casos, pode ser necessário incluir no resultado linhas que não possuem linhas relacionadas em outra tabela (ou seja, todas linhas de uma tabela são selecionadas e apenas linhas relacionadas de outra são adicionadas). Uma conexão deste tipo é chamada externa. Para isso, são utilizadas as palavras-chave OUTER JOIN ... ON ... com o prefixo LEFT ou RIGHT.

Vejamos um exemplo, tendo adicionado anteriormente um novo vendedor - Semuel Piter, que ainda não possui vendas, à tabela Sellers:

Run SQLSELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers2 
LEFT OUTER JOIN Sumproduct 
ON Sellers2.City = Sumproduct.City
GROUP BY Seller_name

Com essa solicitação, extraímos a lista de todos os vendedores do banco de dados e calculamos a quantidade total de mercadorias vendidas por eles em todos os meses. Vemos que não há vendas para o novo vendedor Semuel Piter. Se usássemos uma junção interna, não veríamos o novo vendedor, porque ele não possui registros na tabela Sumproduct. Também podemos mudar a direção da combinação não apenas escrevendo LEFT ou RIGHT, mas também simplesmente alterando a ordem das tabelas (ou seja, os dois registros a seguir darão o mesmo resultado: Sellers LEFT OUTER JOIN Sumproduct e Sumproduct RIGHT _tb lOUTER JOIN Sellers).

Além disso, alguns SGBDs permitem junções externas em um registro simplificado usando os sinais *= e =*, que corresponde a LEFT OUTER JOIN e RIGHT OUTER JOIN, respectivamente. Assim, a consulta anterior poderia ser reescrita da seguinte forma:

SELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers, Sumproduct
WHERE Sellers.City *= Sumproduct.City

Infelizmente MS Access não suporta um registro abreviado para uma junção externa.

5. Junção externa completa (FULL OUTER JOIN)

Há também outro tipo de junção externa - uma junção externa completa, que exibe todas as linhas de ambas as tabelas e une apenas aquelas que podem estar relacionadas. A sintaxe de uma junção externa completa é a seguinte:

SELECT Seller_name, Product
FROM Sellers 
FULL OUTER JOIN Sumproduct 
ON Sellers.City = Sumproduct.City

Novamente, a junção externa completa não é suportada pelos seguintes DBMS: MS Access, MySQL, SQL Server e Sybase. Como contornar esta injustiça, consideraremos na próxima seção.