Uma junção SQL é onde você executa uma consulta que une várias tabelas.
Este tutorial de junções SQL apresenta exemplos básicos de junções SQL, bem como uma introdução aos vários tipos de junção.
Tipos de junção SQL
O padrão ANSI SQL especifica cinco tipos de junções, conforme listado na tabela a seguir.
Tipo de junção | Descrição |
---|---|
INNER JOIN | Retorna linhas quando há pelo menos uma linha em ambas as tabelas que correspondem à condição de junção. |
LEFT OUTER JOIN ou LEFT JOIN | Retorna as linhas que possuem dados na tabela à esquerda (à esquerda do JOIN palavra-chave), mesmo que não haja linhas correspondentes na tabela correta. |
RIGHT OUTER JOIN ou RIGHT JOIN | Retorna as linhas que possuem dados na tabela à direita (à direita do JOIN palavra-chave), mesmo que não haja linhas correspondentes na tabela à esquerda. |
FULL OUTER JOIN ou FULL JOIN | Retorna todas as linhas, desde que haja dados correspondentes em uma das tabelas. |
CROSS JOIN | Retorna linhas que combinam cada linha da primeira tabela com cada linha da segunda tabela. |
Há também outros termos para várias operações de junção, como os seguintes:
Participar | Descrição |
---|---|
Auto-inscrição | Quando uma tabela se une a ela mesma. |
União natural | Uma junção implícita baseada nas colunas comuns nas duas tabelas que estão sendo unidas. |
Equi-join | Uma junção contendo apenas comparações de igualdade no predicado de junção. |
Sintaxe de junção SQL
Junções internas podem ser especificadas em
FROM
ou WHERE
cláusulas. Junções externas e junções cruzadas podem ser especificadas no FROM
cláusula apenas. Para criar uma junção SQL no
FROM
cláusula, faça algo assim:SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ]
Onde
JoinType
especifica que tipo de junção é executada e JoinCondition
define o predicado a ser avaliado para cada par de linhas unidas. Para especificar uma junção no
WHERE
cláusula, faça algo assim:SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ]
Novamente,
JoinCondition
define o predicado a ser avaliado para cada par de linhas unidas. Além disso, tudo entre colchetes (
[]
) é opcional. Tabelas de exemplo para os exemplos neste tutorial
A maioria dos exemplos neste tutorial executa junções nas duas tabelas a seguir.
Os
PetTypes
tabela:+-------------+-----------+ | PetTypeId | PetType | |-------------+-----------| | 1 | Bird | | 2 | Cat | | 3 | Dog | | 4 | Rabbit | +-------------+-----------+ (4 rows affected)
Os
Pets
tabela:+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected)
A União Interna
O SQL
INNER JOIN
retorna linhas quando há pelo menos uma linha em ambas as tabelas que correspondem à condição de junção. SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Resultado:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Para especificar uma junção interna no
FROM
cláusula, usamos INNER JOIN
. Também usamos o ON
palavra-chave para definir o predicado a ser avaliado para cada par de linhas unidas. Independentemente do tipo de junção, qualificamos nossos nomes de coluna com os nomes de tabela. O motivo pelo qual fazemos isso é para evitar qualquer ambiguidade em relação aos nomes das colunas entre as tabelas. Ambas as tabelas podem ter colunas com o mesmo nome (como em nosso exemplo) e, nesses casos, o DBMS não saberá a qual coluna você está se referindo. Prefixar os nomes das colunas com seus nomes de tabela garante que você esteja referenciando a coluna correta e evita erros que possam resultar de qualquer ambiguidade sobre a coluna à qual você está se referindo.
Neste exemplo, ambas as tabelas têm um
PetTypeId
coluna. O Pets.PetTypeId
coluna é uma chave estrangeira para o PetTypes.PetTypeId
coluna, que é a chave primária para essa tabela. Neste exemplo, podemos ver que todos os animais de estimação são retornados, mas nem todos os tipos de animais de estimação são retornados. Não há coelhos nos
Pets
tabela, e assim os Rabbits
tipo de animal de estimação não é retornado. A razão pela qual os
Rabbits
tipo não é retornado é porque o INNER JOIN
só retorna linhas quando há pelo menos uma linha em ambas as tabelas que correspondam à condição de junção. Neste caso, Rabbits
está apenas em uma tabela (o PetTypes
tabela). Observe que o tipo de junção é opcional. Portanto, a maioria (se não todos) DBMSs permite que você omita o
INNER
palavra-chave. Quando você omitir isso (ou seja, especificar apenas JOIN
), supõe-se que seja uma junção interna. Portanto, poderíamos reescrever o exemplo acima para isso:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Além disso, como em qualquer instrução SQL, o
FROM
cláusula pode estar em uma linha inteira, se você preferir:SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId;
Aliases
É uma prática comum usar aliases de tabela ao realizar junções SQL. Os aliases ajudam a tornar o código mais conciso e fácil de ler.
Portanto, poderíamos alterar o exemplo anterior para este:
SELECT
p.PetName,
pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultado:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
O Equi-Join
A junção acima também pode ser chamada de equi-join . Uma junção equi é uma junção que contém apenas comparações de igualdade no predicado de junção.
Outra maneira de escrever a junção acima é assim:
SELECT
p.PetName,
pt.PetType
FROM
Pets p,
PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+
Este é um exemplo de especificação de uma junção interna no
WHERE
cláusula. Nós simplesmente fornecemos uma lista separada por vírgulas das tabelas e, em seguida, um WHERE
doença. Se tivéssemos omitido o WHERE
condição, teríamos acabado com um CROSS JOIN
. Muitos iniciantes acham a sintaxe acima muito mais fácil de entender do que o
INNER JOIN
sintaxe. Sinta-se à vontade para usar esta sintaxe se preferir, no entanto, esteja ciente de que a maioria dos profissionais de SQL prefere usar o INNER JOIN
sintaxe do exemplo anterior. Consulte SQL Inner Join para obter mais exemplos, incluindo uma junção interna que une 3 tabelas.
A associação certa
Também conhecido como
RIGHT OUTER JOIN
, o RIGHT JOIN
retorna as linhas que possuem dados na tabela à direita (à direita do JOIN
palavra-chave), mesmo que não haja linhas correspondentes na tabela à esquerda. SELECT
p.PetName,
pt.PetType
FROM Pets p
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Nesse caso, temos um
PetType
extra valor – Rabbit
– mesmo que não haja nenhum animal de estimação em Pets
mesa desse tipo. Isso resulta em um NULL
valor no PetName
coluna contra Rabbit
. Consulte SQL Right Join para obter mais exemplos, incluindo uma junção direita que une 3 tabelas.
A União Esquerda
Também conhecido como
LEFT OUTER JOIN
, o SQL LEFT JOIN
retorna as linhas que possuem dados na tabela à esquerda (à esquerda do JOIN
palavra-chave), mesmo que não haja linhas correspondentes na tabela correta. Este é o oposto do
RIGHT JOIN
. Se alterarmos o exemplo anterior para usar uma junção à esquerda, obteremos o seguinte resultado.
SELECT
p.PetName,
pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Nesse caso específico, nossos resultados são os mesmos da junção interna.
No entanto, se trocarmos a ordem da tabela em nosso
FROM
cláusula, obteremos um resultado semelhante à junção correta no exemplo anterior. SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Assim, você pode ver que qualquer diferença resultante entre as junções esquerda e direita depende apenas de como você ordena as colunas no
FROM
cláusula. Consulte SQL Left Join para obter mais exemplos, incluindo uma junção esquerda que une 3 tabelas.
A união completa
O SQL
FULL JOIN
(ou FULL OUTER JOIN
) retorna todas as linhas, desde que haja dados correspondentes em uma das tabelas. Em outras palavras, é como ter uma junção esquerda e direita em uma junção.
Aqui está um exemplo de uma junção completa.
SELECT
p.PetName,
pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Isso retorna o mesmo resultado que obtivemos com a junção à direita, mas teria retornado um resultado diferente se houvesse uma linha na tabela à esquerda que não tivesse um valor correspondente na tabela à direita.
Vamos trocar os nomes das tabelas e executá-lo novamente.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Mesmo resultado.
Consulte SQL Full Join para obter mais exemplos, incluindo uma junção completa que une 3 tabelas.
A união cruzada
O SQL
CROSS JOIN
retorna linhas que combinam cada linha da primeira tabela com cada linha da segunda tabela. Em outras palavras, ele retorna o produto cartesiano das linhas das tabelas na junção.
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Bird | | Fetch | Bird | | Scratch | Bird | | Wag | Bird | | Tweet | Bird | | Fluffy | Bird | | Bark | Bird | | Meow | Bird | | Fluffy | Cat | | Fetch | Cat | | Scratch | Cat | | Wag | Cat | | Tweet | Cat | | Fluffy | Cat | | Bark | Cat | | Meow | Cat | | Fluffy | Dog | | Fetch | Dog | | Scratch | Dog | | Wag | Dog | | Tweet | Dog | | Fluffy | Dog | | Bark | Dog | | Meow | Dog | | Fluffy | Rabbit | | Fetch | Rabbit | | Scratch | Rabbit | | Wag | Rabbit | | Tweet | Rabbit | | Fluffy | Rabbit | | Bark | Rabbit | | Meow | Rabbit | +-----------+-----------+ (32 rows affected)
Como você provavelmente pode imaginar, isso pode ser muito perigoso se você executá-lo nas tabelas erradas.
É o mesmo que fazer isso:
SELECT
p.PetName,
pt.PetType
FROM Pets p, PetTypes pt;
Você pode adicionar um
WHERE
cláusula para uma junção cruzada, que a transformará em uma junção interna. Assim:
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Resultado:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Consulte SQL Cross Join para obter mais exemplos.
A união natural
O SQL
NATURAL JOIN
é um tipo de junção equitativa em que o predicado de junção surge implicitamente comparando todas as colunas em ambas as tabelas que possuem os mesmos nomes de coluna nas tabelas unidas. O conjunto de resultados contém apenas uma coluna para cada par de colunas com nomes iguais. Se nenhuma coluna com os mesmos nomes for encontrada, o resultado será uma junção cruzada.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes;
Resultado:
petname | pettype ---------+--------- Fluffy | Cat Fetch | Dog Scratch | Cat Wag | Dog Tweet | Bird Fluffy | Dog Bark | Dog Meow | Cat (8 rows)
Na verdade, a junção natural não é realmente um tipo de junção, conforme considerado pelo padrão ANSI. É uma palavra-chave que você pode inserir opcionalmente para tornar a junção uma junção natural.
Portanto, poderíamos alterar o exemplo acima para
NATURAL INNER JOIN
se quiséssemos:SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes;
Como mencionado anteriormente, as associações internas são o tipo de associação padrão, portanto, se você omitir o tipo de associação (por exemplo,
INNER
, LEFT
, RIGHT
, etc), então ele é tratado como uma junção interna. Se a formatação desses resultados parecer diferente dos resultados anteriores, é porque tive que pular para o PostgreSQL para executar essa consulta. Executei os exemplos anteriores no SQL Server, mas o SQL Server não oferece suporte à junção natural.
Consulte SQL Natural Join para obter mais exemplos, incluindo uma junção natural que une 3 tabelas.
A Auto-Associação
O SQL
SELF JOIN
está unindo uma tabela a si mesma. Um exemplo clássico de autojunção está em uma tabela Employees. Nessa tabela, um funcionário pode se reportar a outro funcionário. Portanto, você pode usar uma autojunção para unir a tabela em sua coluna de ID de funcionário e coluna de ID de gerente.
Suponha que temos a seguinte tabela:
+--------------+-------------+------------+-------------+ | EmployeeId | FirstName | LastName | ReportsTo | |--------------+-------------+------------+-------------| | 1 | Homer | Connery | NULL | | 2 | Bart | Pitt | 1 | | 3 | Maggie | Griffin | 1 | | 4 | Peter | Farnsworth | 2 | | 5 | Marge | Morrison | NULL | | 6 | Lisa | Batch | 5 | | 7 | Dave | Zuckerberg | 6 | | 8 | Vlad | Cook | 7 | +--------------+-------------+------------+-------------+
Podemos fazer um self join nesta tabela para retornar todos os funcionários e seus gerentes.
SELECT
CONCAT(e1.FirstName, ' ', e1.LastName) AS Employee,
CONCAT(e2.FirstName, ' ', e2.LastName) AS Manager
FROM Employees e1
LEFT JOIN Employees e2
ON e1.ReportsTo = e2.EmployeeId;
Resultado:
+------------------+-----------------+ | Employee | Manager | |------------------+-----------------| | Homer Connery | | | Bart Pitt | Homer Connery | | Maggie Griffin | Homer Connery | | Peter Farnsworth | Bart Pitt | | Marge Morrison | | | Lisa Batch | Marge Morrison | | Dave Zuckerberg | Lisa Batch | | Vlad Cook | Dave Zuckerberg | +------------------+-----------------+
Consulte SQL Self Join para obter mais exemplos.