Database
 sql >> Base de Dados >  >> RDS >> Database

Tutorial de junções SQL


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.