Também como LEFT JOIN
, RIGHT JOIN
e se FULL JOIN
encaixa?
Também como LEFT JOIN
, RIGHT JOIN
e se FULL JOIN
encaixa?
Respostas:
Supondo que você esteja ingressando em colunas sem duplicatas, é um caso muito comum:
Uma junção interna de A e B fornece o resultado da interseção A, ou seja, a parte interna de uma interseção do diagrama de Venn .
Uma junção externa de A e B fornece os resultados da união A, ou seja, as partes externas de uma união do diagrama de Venn.
Exemplos
Suponha que você tenha duas tabelas, com uma única coluna cada, e os dados da seguinte maneira:
A B
- -
1 3
2 4
3 5
4 6
Observe que (1,2) são únicos para A, (3,4) são comuns e (5,6) são únicos para B.
Junção interna
Uma junção interna usando uma das consultas equivalentes fornece a interseção das duas tabelas, ou seja, as duas linhas que elas têm em comum.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Junção externa esquerda
Uma junção externa esquerda fornecerá todas as linhas em A, mais as linhas comuns em B.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Junção externa direita
Uma junção externa direita fornecerá todas as linhas em B, mais as linhas comuns em A.
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
Junção externa completa
Uma junção externa completa fornecerá a união de A e B, ou seja, todas as linhas em A e todas as linhas em B. Se algo em A não tiver um dado correspondente em B, a parte B será nula e vice-versa. versa.
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
Os diagramas de Venn realmente não fazem isso por mim.
Eles não mostram nenhuma distinção entre uma junção cruzada e uma junção interna, por exemplo, ou geralmente mostram qualquer distinção entre diferentes tipos de predicado de junção ou fornecem uma estrutura para raciocinar sobre como eles irão operar.
Não há substituto para a compreensão do processamento lógico e é relativamente simples de entender de qualquer maneira.
on
cláusula em todas as linhas da etapa 1, mantendo aquelas nas quais o predicado avalia comotrue
(Observação: na prática, o otimizador de consulta pode encontrar maneiras mais eficientes de executar a consulta do que a descrição puramente lógica acima, mas o resultado final deve ser o mesmo)
Vou começar com uma versão animada de uma junção externa completa . Mais explicações a seguir.
Tabelas de origem
Comece primeiro com um CROSS JOIN
(produto cartesiano AKA). Isso não possui uma ON
cláusula e simplesmente retorna todas as combinações de linhas das duas tabelas.
SELECIONE A.Cor, B.Cor A partir de uma junção cruzada B
Associações interna e externa têm um predicado de cláusula "ON".
SELECIONE A.Colour, B.Colour A PARTIR DE UMA UNIDADE INTERIOR B EM A.Colour = B.Colour
A descrição acima é a junção equi clássica.
A condição de junção interna não precisa necessariamente ser uma condição de igualdade e não precisa fazer referência a colunas de ambas (ou mesmo de uma) das tabelas. A avaliação A.Colour NOT IN ('Green','Blue')
em cada linha da junção cruzada retorna.
SELECIONE A.Cor, B.Cor A PARTIR DE UMA UNIÃO INTERIOR B EM 1 = 1
A condição de junção é avaliada como verdadeira para todas as linhas no resultado da junção cruzada, portanto, é exatamente o mesmo que uma junção cruzada. Não vou repetir a imagem das 16 linhas novamente.
Junções externas são avaliadas logicamente da mesma maneira que junções internas, exceto se uma linha da tabela esquerda (para uma junção esquerda) não se unir a nenhuma linha da tabela à direita, ela é preservada no resultado com NULL
valores para o colunas da direita.
Isso simplesmente restringe o resultado anterior para retornar apenas as linhas onde B.Colour IS NULL
. Nesse caso em particular, essas serão as linhas que foram preservadas, pois não tinham correspondência na tabela à direita e a consulta retorna a única linha vermelha que não corresponde à tabela B
. Isso é conhecido como uma junção anti-semi.
É importante selecionar uma coluna para o IS NULL
teste que não seja anulável ou para o qual a condição de junção garanta a NULL
exclusão de quaisquer valores para que esse padrão funcione corretamente e evite apenas trazer de volta as linhas que possuem um NULL
valor para esse padrão. coluna, além das linhas não correspondidas.
As junções externas à direita agem de maneira semelhante às junções externas à esquerda, exceto que preservam linhas não correspondentes da tabela direita e estendem nulo as colunas à esquerda.
As junções externas completas combinam o comportamento das junções esquerda e direita e preservam as linhas não correspondentes das tabelas esquerda e direita.
Nenhuma linha na junção cruzada corresponde ao 1=0
predicado. Todas as linhas de ambos os lados são preservadas usando regras normais de junção externa com NULL nas colunas da tabela do outro lado.
Com uma pequena alteração na consulta anterior, era possível simular uma UNION ALL
das duas tabelas.
Observe que a WHERE
cláusula (se presente) é executada logicamente após a associação. Um erro comum é executar uma junção externa esquerda e incluir uma cláusula WHERE com uma condição na tabela direita que acaba excluindo as linhas não correspondentes. O exemplo acima acaba executando a junção externa ...
... E então a cláusula "Where" é executada. NULL= 'Green'
não é avaliado como verdadeiro, de modo que a linha preservada pela junção externa acaba sendo descartada (junto com a azul) efetivamente convertendo a junção novamente em interna.
Se a intenção fosse incluir apenas linhas de B, em que Cor é Verde, e todas as linhas de A, independentemente da sintaxe correta.
Veja estes exemplos executados ao vivo no SQLFiddle.com .
As junções são usadas para combinar os dados de duas tabelas, com o resultado sendo uma nova tabela temporária. As junções são realizadas com base em algo chamado predicado, que especifica a condição a ser usada para realizar uma junção. A diferença entre uma junção interna e uma junção externa é que uma junção interna retornará apenas as linhas que realmente correspondem com base no predicado da junção. Por exemplo: vamos considerar a tabela Empregado e Local:
Junção interna: - A junção interna cria uma nova tabela de resultados combinando os valores da coluna de duas tabelas ( Funcionário e Local ) com base no predicado de junção. A consulta compara cada linha de Employee com cada linha de Location para encontrar todos os pares de linhas que satisfazem o predicado de junção. Quando o predicado de junção é satisfeito pela correspondência de valores não NULL, os valores da coluna para cada par de linhas correspondentes de Employee e Location são combinados em uma linha de resultado. Aqui está a aparência do SQL para uma junção interna:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Agora, aqui está como seria o resultado da execução desse SQL:
Associação externa: - Uma associação externa não exige que cada registro nas duas tabelas associadas tenha um registro correspondente. A tabela unida retém cada registro - mesmo que não exista outro registro correspondente. As junções externas subdividem-se ainda mais em junções externas esquerdas e externas, dependendo de quais linhas da tabela são mantidas (esquerda ou direita).
Junção Externa Esquerda: - O resultado de uma junção externa esquerda (ou simplesmente junção esquerda) para as tabelas Employee e Location sempre contém todos os registros da tabela "esquerda" ( Employee ), mesmo que a condição de junção não encontre nenhum registro correspondente em a tabela "certa" ( localização ). Aqui está a aparência do SQL para uma junção externa esquerda, usando as tabelas acima:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Agora, aqui está como seria o resultado da execução desse SQL:
Junção externa direita: - Uma junção externa direita (ou junção direita) se assemelha bastante a uma junção externa esquerda, exceto com o tratamento das tabelas invertidas. Cada linha da tabela "direita" ( Local ) aparecerá na tabela unida pelo menos uma vez. Se não existir nenhuma linha correspondente da tabela "esquerda" ( Funcionário ), NULL aparecerá nas colunas de Funcionário para os registros que não têm correspondência no Local . É assim que o SQL se parece:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Usando as tabelas acima, podemos mostrar como seria o conjunto de resultados de uma junção externa direita:
Junções externas completas: - Junção externa completa ou Junção completa serve para reter as informações não correspondentes incluindo linhas não correspondentes nos resultados de uma junção, use uma junção externa completa. Inclui todas as linhas de ambas as tabelas, independentemente de a outra tabela ter ou não um valor correspondente.
Recupere apenas as linhas correspondentes, ou seja A intersect B
,.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Selecione todos os registros da primeira tabela e quaisquer registros na segunda tabela que correspondam às chaves unidas.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Selecione todos os registros da segunda tabela e quaisquer registros na primeira tabela que correspondam às chaves unidas.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Em palavras simples:
Uma junção interna recupera apenas as linhas correspondentes.
Enquanto uma junção externa recupera as linhas correspondentes de uma tabela e todas as linhas da outra tabela .... o resultado depende de qual você está usando:
Esquerda : linhas correspondentes na tabela direita e todas as linhas na tabela esquerda
Direita : linhas correspondentes na tabela esquerda e todas as linhas na tabela direita ou
Completo : todas as linhas em todas as tabelas. Não importa se há uma correspondência ou não
Uma junção interna mostra apenas linhas se houver um registro correspondente no outro lado (direito) da junção.
Uma junção externa (esquerda) mostra linhas para cada registro no lado esquerdo, mesmo se não houver linhas correspondentes no outro lado (direito) da junção. Se não houver linha correspondente, as colunas do outro lado (direito) mostrariam NULLs.
Associações internas exigem que um registro com um ID relacionado exista na tabela associada.
As junções externas retornarão registros para o lado esquerdo, mesmo que não exista nada para o lado direito.
Por exemplo, você tem uma tabela Orders e uma OrderDetails. Eles são relacionados por um "CódigoDoPedido".
Encomendas
Detalhes do pedido
O pedido
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
retornará apenas pedidos que também possuem algo na tabela OrderDetails.
Se você alterá-lo para OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
em seguida, ele retornará registros da tabela Pedidos, mesmo que eles não tenham registros OrderDetails.
Você pode usar isso para encontrar pedidos que não possuem nenhum OrderDetails indicando um possível pedido órfão adicionando uma cláusula where como WHERE OrderDetails.OrderID IS NULL
.
SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
para SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
(MySQL) com sucesso. Eu não tinha certeza sobre as condições adicionais, eles misturam bem ...
Em palavras simples:
Junção interna -> Obtenha SOMENTE registros comuns das tabelas pai e filho WHERE a chave primária da tabela pai corresponde à chave estrangeira na tabela filho.
Associação à esquerda ->
pseudo-código
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Junção direita : exatamente o oposto da junção esquerda. Coloque o nome da tabela em LEFT JOIN no lado direito em Right join, você obtém a mesma saída que LEFT JOIN.
Junção externa : mostra todos os registros nas duas tabelasNo matter what
. Se os registros na tabela Esquerda não corresponderem à tabela direita com base na chave Primária e Externa, use o valor NULL como resultado da associação.
Exemplo:
Vamos assumir agora para 2 tabelas
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Aqui, a tabela employee é a tabela Master, phone_numbers_employees é a tabela filho (ela contém uma emp_id
chave estrangeira que conecta employee.id
sua tabela filho).
Junções internas
Pegue os registros de 2 tabelas SOMENTE SE A chave primária da tabela de funcionários (seu ID) corresponde à chave estrangeira da tabela filho phone_numbers_employees (emp_id) .
Portanto, a consulta seria:
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Aqui, pegue apenas as linhas correspondentes na chave primária = chave estrangeira, conforme explicado acima. Aqui, as linhas não correspondentes na chave primária = chave estrangeira são ignoradas como resultado da junção.
Junções à esquerda :
A junção esquerda mantém todas as linhas da tabela esquerda, independentemente de haver uma linha que corresponda à tabela direita.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Junções externas :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Diagramaticamente, ele se parece com:
Você usa INNER JOIN
para retornar todas as linhas das duas tabelas em que há uma correspondência. ou seja, na tabela resultante, todas as linhas e colunas terão valores.
Na OUTER JOIN
tabela resultante pode ter colunas vazias. A junção externa pode ser LEFT
ou RIGHT
.
LEFT OUTER JOIN
retorna todas as linhas da primeira tabela, mesmo se não houver correspondências na segunda tabela.
RIGHT OUTER JOIN
retorna todas as linhas da segunda tabela, mesmo se não houver correspondências na primeira tabela.
Esta é uma boa explicação diagramática para todos os tipos de junções
fonte: http://ssiddique.info/understanding-sql-joins-in-easy-way.html
INNER JOIN
requer que haja pelo menos uma correspondência na comparação das duas tabelas. Por exemplo, a tabela A e a tabela B, que implica A ٨ B (interseção A).
LEFT OUTER JOIN
e LEFT JOIN
são iguais. Ele fornece todos os registros correspondentes nas duas tabelas e todas as possibilidades da tabela esquerda.
Da mesma forma, RIGHT OUTER JOIN
e RIGHT JOIN
são os mesmos. Ele fornece todos os registros correspondentes nas duas tabelas e todas as possibilidades da tabela correta.
FULL JOIN
é a combinação de LEFT OUTER JOIN
e RIGHT OUTER JOIN
sem duplicação.
A resposta está no significado de cada um, assim nos resultados.
Nota:
EmSQLite
não existeRIGHT OUTER JOIN
ouFULL OUTER JOIN
.
E tambémMySQL
não háFULL OUTER JOIN
.
Minha resposta é baseada na nota acima .
Quando você tem duas tabelas como estas:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTTER JOIN:
Você pode ter todos esses dados de tabelas com CROSS JOIN
ou apenas os ,
seguintes:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN:
Quando você deseja adicionar um filtro aos resultados acima com base em uma relação como a que table1.id = table2.id
você pode usar INNER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
ESQUERDA [EXTERNA] JOIN:
Quando você quiser ter todas as linhas de uma das tabelas no resultado acima, com a mesma relação, poderá usar LEFT JOIN
:
(Para RIGHT JOIN, basta mudar o local das tabelas)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
JUNÇÃO EXTERNA COMPLETA:
Quando você também quiser ter todas as linhas da outra tabela em seus resultados, poderá usar FULL OUTER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Bem, conforme sua necessidade, você escolhe cada uma que atenda às suas necessidades;).
full outer join
no MySQL.
Junção interna.
Uma junção está combinando as linhas de duas tabelas. Uma junção interna tenta corresponder as duas tabelas com base nos critérios especificados na consulta e retorna apenas as linhas correspondentes. Se uma linha da primeira tabela na junção corresponder a duas linhas na segunda tabela, duas linhas serão retornadas nos resultados. Se houver uma linha na primeira tabela que não corresponda a uma linha na segunda, ela não será retornada; da mesma forma, se houver uma linha na segunda tabela que não corresponda a uma linha na primeira, ela não será retornada.
Junção externa.
Uma junção esquerda tenta encontrar as linhas correspondentes da primeira tabela às linhas da segunda tabela. Se não conseguir encontrar uma correspondência, retornará as colunas da primeira tabela e deixará as colunas da segunda tabela em branco (nulo).
INNER JOIN
junção mais típica para duas ou mais tabelas. Retorna a correspondência de dados na tabela ON primarykey e forignkey.OUTER JOIN
é o mesmo que INNER JOIN
, mas também inclui NULL
dados no ResultSet.
LEFT JOIN
= INNER JOIN
+ Dados incomparáveis da tabela esquerda com Null
correspondência na tabela direita.RIGHT JOIN
= INNER JOIN
+ Dados incomparáveis da tabela da direita com Null
correspondência na tabela da esquerda.FULL JOIN
= INNER JOIN
+ Dados incomparáveis nas tabelas direita e esquerda com Null
correspondências.INNER JOIN
e OUTER JOIN
podemos escrever consultas de auto-junção.Por exemplo:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
Não vejo muitos detalhes sobre desempenho e otimizador nas outras respostas.
Às vezes é bom saber que apenas INNER JOIN
é associativo, o que significa que o otimizador tem mais opções para brincar com ele. Ele pode reordenar a ordem de junção para torná-lo mais rápido, mantendo o mesmo resultado. O otimizador pode usar a maioria dos modos de junção.
Geralmente, é uma boa prática tentar usar em INNER JOIN
vez dos diferentes tipos de junções. (Obviamente, se for possível, considerando o conjunto de resultados esperado.)
Existem alguns bons exemplos e explicações aqui sobre esse estranho comportamento associativo:
INNER JOIN
é mais lento do que LEFT JOIN
na maioria das vezes, E as pessoas podem usar em LEFT JOIN
vez de INNER JOIN
adicionar um WHERE
para remover NULL
resultados inesperados ;).
INNER
é mais lento?
Tendo criticado o muito amado diagrama de Venn em tom de vermelho, achei justo postar minha própria tentativa.
Embora a resposta de @Martin Smith seja o melhor desse grupo, ele só mostra a coluna chave de cada tabela, enquanto eu acho que idealmente colunas não chave também devem ser mostradas.
O melhor que pude fazer na meia hora permitida, ainda não acho que isso mostre adequadamente que os nulos estão lá devido à ausência de valores-chave TableB
ou que OUTER JOIN
na verdade é uma união e não uma união:
TableA a LEFT OUTER JOIN TableB b
porTableB B RIGHT OUTER JOIN TableA a
O algoritmo preciso para INNER JOIN
, LEFT/RIGHT OUTER JOIN
são os seguintes:
a
(a, b[i])
ON ...
cláusula em relação a cada par:ON( a, b[i] ) = true/false?
true
, retorne a linha combinada (a, b[i])
.Outer Join
retorne um par (virtual) usando Null
para todas as colunas da outra tabela: (a, Null)
para junção externa ESQUERDA ou (Null, b)
junção externa DIREITA. Isso é para garantir que todas as linhas da primeira tabela existam nos resultados finais.Nota: a condição especificada na ON
cláusula pode ser qualquer coisa, não é necessário usar Chaves Primárias (e você não precisa sempre consultar as Colunas das duas tabelas)! Por exemplo:
... ON T1.title = T2.title AND T1.version < T2.version
(=> veja esta postagem como um exemplo de uso: selecione apenas linhas com valor máximo em uma coluna )... ON T1.y IS NULL
... ON 1 = 0
(apenas como amostra)Nota: Junção esquerda = Junção externa esquerda, Junção direita = Junção externa direita.
Definições mais simples
Junção interna: retorna registros correspondentes das duas tabelas.
Junção externa completa: retorna registros correspondentes e não correspondentes de ambas as tabelas com nulo para registros não correspondentes de ambas as tabelas .
Junção externa esquerda: retorna registros correspondentes e não correspondentes apenas da tabela no lado esquerdo .
União externa direita: retorna registros correspondentes e não correspondentes somente da tabela no lado direito .
Em resumo
Corresponde + Esquerda sem correspondência + Direita sem correspondência = Junção externa completa
Corresponde + Esquerda sem correspondência = Junção externa esquerda
Combinado + Direito incomparável = União externa direita
Correspondido = Junção interna
Em termos simples,
1. JUNÇÃO INTERNA OU EQUI JUNTA: Retorna o conjunto de resultados que corresponde apenas à condição nas duas tabelas.
2. JUNÇÃO EXTERNA: Retorna o conjunto de resultados de todos os valores de ambas as tabelas, mesmo que haja uma condição correspondente ou não.
3. JUNTA ESQUERDA: Retorna o conjunto de resultados de todos os valores da tabela esquerda e apenas das linhas que correspondem à condição na tabela direita.
4. JUNTA CERTA: Retorna o conjunto de resultados de todos os valores da tabela direita e apenas das linhas que correspondem à condição na tabela esquerda.
5. JUNÇÃO COMPLETA: Junção completa e Junção externa completa são iguais.
Exemplos
Suponha que você tenha duas tabelas, com uma única coluna cada, e os dados da seguinte maneira:
A B
- -
1 3
2 4
3 5
4 6
7
8
Observe que (1,2,7,8) são únicos para A, (3,4) são comuns e (5,6) são únicos para B.
A palavra-chave INNER JOIN seleciona todas as linhas de ambas as tabelas, desde que a condição seja satisfatória. Essa palavra-chave criará o conjunto de resultados combinando todas as linhas de ambas as tabelas em que a condição satisfaz, ou seja, o valor do campo comum será o mesmo.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
Resultado:
a | b
--+--
3 | 3
4 | 4
Essa junção retorna todas as linhas da tabela no lado esquerdo da junção e as linhas correspondentes para a tabela no lado direito da junção. As linhas para as quais não há linha correspondente no lado direito, o conjunto de resultados conterá nulo. LEFT JOIN também é conhecido como LEFT OUTER JOIN
.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
Resultado:
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
7 | null
8 | null
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
Resultado:
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
JUNÇÃO COMPLETA (EXTERIOR) :
FULL JOIN cria o conjunto de resultados combinando o resultado de LEFT JOIN e RIGHT JOIN. O conjunto de resultados conterá todas as linhas das duas tabelas. As linhas para as quais não há correspondência, o conjunto de resultados conterá valores NULL.
select * from a FULL OUTER JOIN b on a.a = b.b;
Resultado:
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
7 | null
8 | null
Junção interna - uma junção interna usando uma das consultas equivalentes fornece a interseção das duas tabelas , ou seja, as duas linhas que elas têm em comum.
Junção externa esquerda - uma junção externa esquerda fornecerá todas as linhas em A, mais as linhas comuns em B.
Junção externa completa - Uma junção externa completa fornecerá a união de A e B, ou seja, Todas as linhas em A e todas as linhas em B. Se algo em A não tiver um dado correspondente em B, a parte B será nulo e vice-versa
Join is not an intersection unless the tables have the same columns
Não. Você pode ingressar em qualquer coluna que desejar e, se o valor corresponder, elas se unirão.
1. Junção interna: também chamada de Junção. Ele retorna as linhas presentes na tabela Esquerda e na tabela direita somente se houver uma correspondência . Caso contrário, ele retornará zero registros.
Exemplo:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2. Junção externa completa: também chamada de Junção completa. Retorna todas as linhas presentes nas tabelas esquerda e direita.
Exemplo:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3. Junção externa esquerda: ou simplesmente chamado como Junção esquerda. Retorna todas as linhas presentes na tabela esquerda e as linhas correspondentes da tabela direita (se houver).
4. Junção externa direita: também chamada de Junta direita. Ele retorna linhas correspondentes da tabela esquerda (se houver) e todas as linhas presentes na tabela Direita.
Vantagens das junções
Considere abaixo 2 tabelas:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Departamento
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Principalmente escrito como JOIN em consultas sql. Retorna apenas os registros correspondentes entre as tabelas.
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
Como você vê acima, Jose
não é impresso no EMP na saída, pois o dept_id 6
não encontra uma correspondência na tabela Departamento. Da mesma forma, HR
e as R&D
linhas não são impressas no Departamento tabela , pois não encontraram uma correspondência na tabela Emp.
Portanto, INNER JOIN ou apenas JOIN, retorna apenas as linhas correspondentes.
Isso retorna todos os registros da tabela ESQUERDA e apenas os registros correspondentes da tabela DIREITA.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
Portanto, se você observar a saída acima, todos os registros da tabela ESQUERDA (Emp) serão impressos apenas com registros correspondentes da tabela DIREITA.
HR
e as R&D
linhas não são impressas na tabela Departamento , pois não encontraram uma correspondência na tabela Emp em dept_id.
Portanto, LEFT JOIN retorna TODAS as linhas da tabela Esquerda e apenas as linhas correspondentes da tabela RIGHT.
Também pode verificar a DEMO aqui .
Por favor, veja a resposta de Martin Smith para obter melhores ilustrações e explicações sobre as diferentes junções, incluindo e especialmente as diferenças entre FULL OUTER JOIN
, RIGHT OUTER JOIN
e LEFT OUTER JOIN
.
Essas duas tabelas formam uma base para a representação dos JOIN
s abaixo:
SELECT *
FROM citizen
CROSS JOIN postalcode
O resultado serão os produtos cartesianos de todas as combinações. Nenhuma JOIN
condição necessária:
INNER JOIN
é o mesmo que simplesmente: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
O resultado serão combinações que satisfazem a JOIN
condição necessária :
LEFT OUTER JOIN
é o mesmo que LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
O resultado será tudo, citizen
mesmo que não haja correspondências postalcode
. Novamente, uma JOIN
condição é necessária:
Todos os exemplos foram executados em um Oracle 18c. Eles estão disponíveis no dbfiddle.uk, que também é de onde vieram as capturas de tela das tabelas.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
JOIN
eWHERE
CROSS JOIN
resultando em linhas como A idéia geral / INNER JOIN
:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Usar CROSS JOIN
para obter o resultado de a LEFT OUTER JOIN
requer truques como adicionar em uma NULL
linha. Está omitido.
INNER JOIN
torna-se um produto cartesiano. É o mesmo que The General Idea / CROSS JOIN
:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
É aqui que a junção interna pode realmente ser vista como a junção cruzada com resultados que não correspondem à condição removida. Aqui, nenhuma das linhas resultantes é removida.
Usar INNER JOIN
para obter o resultado de um LEFT OUTER JOIN
também requer truques. Está omitido.
LEFT JOIN
resulta em linhas como A idéia geral / CROSS JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN
resulta em linhas como A idéia geral / INNER JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
Uma pesquisa de imagens na Internet em "sql join cross inner outer" mostrará uma infinidade de diagramas de Venn. Eu costumava ter uma cópia impressa de uma na minha mesa. Mas há problemas com a representação.
O diagrama de Venn é excelente para a teoria dos conjuntos, onde um elemento pode estar em um ou nos dois conjuntos. Mas para bancos de dados, um elemento em um "conjunto" parece, para mim, uma linha em uma tabela e, portanto, também não está presente em nenhuma outra tabela. Não existe uma linha presente em várias tabelas. Uma linha é exclusiva para a tabela.
As junções automáticas são um caso de canto em que cada elemento é de fato o mesmo nos dois conjuntos. Mas ainda não está livre de nenhum dos problemas abaixo.
O conjunto A
representa o conjunto à esquerda (a citizen
tabela) e o conjunto B
é o conjunto à direita (a postalcode
tabela) na discussão abaixo.
Todos os elementos de ambos os conjuntos são combinados com todos os elementos do outro conjunto, o que significa que precisamos de A
quantidade de todos os B
elementos e B
quantidade de todos os A
elementos para representar adequadamente esse produto cartesiano. A teoria dos conjuntos não é feita para vários elementos idênticos em um conjunto, então acho que os diagramas de Venn representam adequadamente impraticável / impossível. Parece que não UNION
se encaixa.
As linhas são distintas. São UNION
7 linhas no total. Mas eles são incompatíveis para um SQL
conjunto de resultados comum . E não é assim que CROSS JOIN
funciona:
Tentando representá-lo assim:
..mas agora parece apenas um INTERSECTION
, o que certamente não é . Além disso, não há nenhum elemento no INTERSECTION
que está realmente em qualquer um dos dois conjuntos distintos. No entanto, parece muito com os resultados pesquisáveis semelhantes a este:
Para referência, um resultado pesquisável para CROSS JOIN
s pode ser visto em Tutorialgateway . O INTERSECTION
, assim como este, está vazio.
O valor de um elemento depende da JOIN
condição. É possível representar isso sob a condição de que cada linha se torne exclusiva para essa condição. O significado id=x
é verdadeiro apenas para uma linha. Quando uma linha na tabela A
( citizen
) corresponde a várias linhas na tabela B
( postalcode
) sob a JOIN
condição, o resultado tem os mesmos problemas que CROSS JOIN
: A linha precisa ser representada várias vezes e a teoria dos conjuntos não é realmente feita para isso. Sob a condição de exclusividade, o diagrama pode funcionar, mas lembre-se de que a JOIN
condição determina a colocação de um elemento no diagrama. Observando apenas os valores da JOIN
condição com o restante da linha logo após o passeio:
Essa representação se desfaz completamente ao usar a INNER JOIN
com uma ON 1 = 1
condição que a transforma em a CROSS JOIN
.
Com um self- JOIN
, as linhas são de fato elementos identais em ambas as tabelas, mas representam as tabelas como ambas A
e B
não são muito adequadas. Por exemplo, uma auto- JOIN
condição comum que faz com que um elemento A
corresponda a um elemento diferente em B é ON A.parent = B.child
fazer a correspondência de A
para B
elementos separados. Dos exemplos que seriam SQL
assim:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Significado Smith é o líder de Green e Jensen.
Novamente, os problemas começam quando uma linha possui várias correspondências com as linhas na outra tabela. Isso é ainda mais complicado, pois OUTER JOIN
pode corresponder ao conjunto vazio. Mas, na teoria dos conjuntos, a união de qualquer conjunto C
e de um conjunto vazio é sempre justa C
. O conjunto vazio não adiciona nada. A representação disso LEFT OUTER JOIN
é geralmente apenas mostrando tudo A
para ilustrar que as linhas A
são selecionadas independentemente de haver uma correspondência ou não B
. Os "elementos correspondentes", no entanto, têm os mesmos problemas que a ilustração acima. Eles dependem da condição. E o conjunto vazio parece ter vagado até A
:
Localizando todas as linhas de a CROSS JOIN
com Smith e código postal na Lua:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Agora, o diagrama de Venn não é usado para refletir o JOIN
. É usado apenas para a WHERE
cláusula:
..e isso faz sentido.
Como explicado, um INNER JOIN
não é realmente um INTERSECT
. No entanto, INTERSECT
s pode ser usado em resultados de consultas separadas. Aqui, um diagrama de Venn faz sentido, porque os elementos das consultas separadas são de fato linhas que pertencem a apenas um dos resultados ou a ambos. A interseção obviamente retornará apenas resultados onde a linha estiver presente nas duas consultas. Isso SQL
resultará na mesma linha que a acima WHERE
, e o diagrama de Venn também será o mesmo:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
Um OUTER JOIN
não é um UNION
. No entanto, UNION
trabalhe nas mesmas condições que INTERSECT
, resultando em um retorno de todos os resultados combinando os dois SELECT
s:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
que é equivalente a:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..e fornece o resultado:
Também aqui um diagrama de Venn faz sentido:
Uma observação importante é que isso só funciona quando a estrutura dos resultados dos dois SELECTs é a mesma, permitindo uma comparação ou união. Os resultados desses dois não permitirão que:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
.. tentar combinar os resultados com UNION
dá uma
ORA-01790: expression must have same datatype as corresponding expression
Para mais informações, leia Diga NÃO aos diagramas de Venn ao explicar JOINs e sql joins como diagrama de venn . Ambos também cobrem EXCEPT
.
Há muitas boas respostas aqui com exemplos de álgebra relacional muito precisos . Aqui está uma resposta muito simplificada que pode ser útil para codificadores amadores ou iniciantes com dilemas de codificação SQL.
Basicamente, na maioria das vezes, as consultas se JOIN
resumem a dois casos:
Para um SELECT
subconjunto de dados A
:
INNER JOIN
quando os dados relacionados que B
você procura DEVEM existir por design do banco de dados;LEFT JOIN
quando os dados relacionados que B
você procura MIGHT ou MIGH NOT existem por design do banco de dados.A diferença entre inner join
e outer join
é a seguinte:
Inner join
é uma junção que combina tabelas com base em tuplas correspondentes, enquanto que outer join
é uma junção que combina tabela com base em tuplas correspondentes e não correspondentes.Inner join
mescla a linha correspondente de duas tabelas na qual a linha não correspondente é omitida, enquanto outer join
mescla linhas de duas tabelas e as linhas não correspondentes são preenchidas com valor nulo.Inner join
é como uma operação de interseção, enquanto outer join
é como uma operação de união.Inner join
são dois tipos, enquanto outer join
são três tipos.outer join
é mais rápido que inner join
.