Explicação de self-joins

84

Não entendo a necessidade de auto-junções. Alguém pode explicar para mim?

Um exemplo simples seria muito útil.

Alex Gordon
fonte

Respostas:

95

Você pode ver a auto-junção como duas tabelas idênticas. Mas na normalização, você não pode criar duas cópias da tabela, portanto, apenas simule duas tabelas com auto-junção.

Suponha que você tenha duas tabelas:

Tabela emp1

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

Tabela emp2

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

Agora, se você deseja obter o nome de cada funcionário com os nomes de seu chefe:

select c1.Name , c2.Name As Boss
from emp1 c1
    inner join emp2 c2 on c1.Boss_id = c2.Id

O que resultará na seguinte tabela:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF
política inútil
fonte
1
Neste exemplo, não consigo descobrir quem é o chefe. Embora o exp seja bom e fácil de entender.
MAC
2
left joinAcho melhor não deixar de fora o empregado (ou patrão) que não tem patrão; o cão superior!
Rockin4Life33
22

É bastante comum quando você tem uma tabela que faz referência a si mesma. Exemplo: uma tabela de funcionários onde cada funcionário pode ter um gerente, e você deseja listar todos os funcionários e o nome de seu gerente.

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id
Windyjonas
fonte
18

Uma junção automática é uma junção de uma tabela consigo mesma.

Um caso de uso comum é quando a tabela armazena entidades (registros) que possuem uma relação hierárquica entre elas . Por exemplo, uma tabela contendo informações pessoais (nome, data de nascimento, endereço ...) e incluindo uma coluna onde o ID do pai (e / ou da mãe) está incluído. Então, com uma pequena consulta como

SELECT Child.ID, Child.Name, Child.PhoneNumber, Father.Name, Father.PhoneNumber
FROM myTableOfPersons As Child
LEFT OUTER JOIN  myTableOfPersons As Father ON Child.FatherId = Father.ID
WHERE Child.City = 'Chicago'  -- Or some other condition or none

podemos obter informações sobre o filho e o pai (e a mãe, com um segundo self join etc. e até mesmo os avós etc ...) na mesma consulta.

mjv
fonte
5

Digamos que você tenha uma mesa users, configurada assim:

  • ID do usuário
  • nome do usuário
  • ID de gerente do usuário

Nessa situação, se você quiser extrair as informações do usuário e as do gerente em uma consulta, pode fazer o seguinte:

SELECT users.user_id, users.user_name, managers.user_id AS manager_id, managers.user_name AS manager_name INNER JOIN users AS manager ON users.manager_id=manager.user_id
ceejayoz
fonte
4

Eles são úteis se sua tabela for autorreferencial. Por exemplo, para uma tabela de páginas, cada página pode ter um link nexte previous. Esses seriam os IDs de outras páginas na mesma tabela. Se em algum ponto você quiser obter um triplo de páginas sucessivas, você fará duas autojunções nas colunas nexte previouscom a mesma idcoluna da tabela .

Max Shawabkeh
fonte
4

Imagine uma tabela chamada Employeeconforme descrito abaixo. Todos os funcionários têm um gerente que também é funcionário (talvez exceto o CEO, cujo manager_id seria nulo)

Table (Employee): 

int id,
varchar name,
int manager_id

Você pode então usar o seguinte selecionar para localizar todos os funcionários e seus gerentes:

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id
Klaus Byskov Pedersen
fonte
4

Sem a capacidade de uma tabela fazer referência a si mesma, teríamos que criar tantas tabelas para níveis de hierarquia quanto o número de camadas na hierarquia. Mas, como essa funcionalidade está disponível, você associa a tabela a ela mesma e o sql a trata como duas tabelas separadas, de modo que tudo é armazenado em um só lugar.

Eugene
fonte
mas agora você (com sorte) entende o que aconteceria se a auto-referência não estivesse disponível.
Eugene,
4

Além das respostas mencionadas acima (que estão muito bem explicadas), gostaria de acrescentar um exemplo para que o uso do Self Join possa ser facilmente mostrado. Suponha que você tenha uma tabela chamada CUSTOMERS com os seguintes atributos: CustomerID, CustomerName, ContactName, City, Country. Agora você deseja listar todos aqueles que são da "mesma cidade". Você terá que pensar em uma réplica desta tabela para que possamos juntá-los com base em CITY. A consulta abaixo mostrará claramente o que significa:

SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2, 
A.City
FROM Customers A, Customers B
WHERE A.CustomerID <> B.CustomerID
AND A.City = B.City 
ORDER BY A.City;
Mazhar MIK
fonte
3
+1 Esta resposta é muito importante porque há muitas perguntas SQL no SO para as quais a resposta é "usar uma auto-junção", que as pessoas tendem a não ver quando não têm uma auto-referência explícita (hierárquica).
JimmyB
1
Mesmo que esta seja uma cópia da massa da w3schools, acho que a resposta acima não explica a auto-junção, mas a junção interna, que é diferente.
George K
3

Existem muitas respostas corretas aqui, mas há uma variação que é igualmente correta. Você pode colocar suas condições de junção na instrução de junção em vez da cláusula WHERE.

SELECT e1.emp_id AS 'Emp_ID'
  , e1.emp_name AS 'Emp_Name'
  , e2.emp_id AS 'Manager_ID'
  , e2.emp_name AS 'Manager_Name'
FROM Employee e1 RIGHT JOIN Employee e2 ON e1.emp_id = e2.emp_id

Lembre-se de que às vezes você deseja e1.manager_id> e2.id

A vantagem de saber os dois cenários é que às vezes você tem uma tonelada de condições WHERE ou JOIN e deseja colocar suas condições de self join na outra cláusula para manter seu código legível.

Ninguém abordou o que acontece quando um funcionário não tem um gerente. Hã? Eles não estão incluídos no conjunto de resultados. E se você quiser incluir funcionários que não têm gerentes, mas não quiser que combinações incorretas sejam retornadas?

Experimente este cachorrinho;

SELECT e1.emp_id AS 'Emp_ID'
   , e1.emp_name AS 'Emp_Name'
   , e2.emp_id AS 'Manager_ID'
   , e2.emp_name AS 'Manager_Name'
FROM Employee e1 LEFT JOIN Employee e2 
   ON e1.emp_id = e2.emp_id
   AND e1.emp_name = e2.emp_name
   AND e1.every_other_matching_column = e2.every_other_matching_column
BClaydon
fonte
1
Hm, no cachorrinho, por que você entra em "maior que" em vez de "igual"?
Marcel
1
Oi. Eu vi que alguns exemplos usam "FROM xxx, yyy WHERE" e alguns outros "FROM xxx JOIN yyy WHERE". Você poderia explicar a diferença, por favor?
skan
@Skan Essa é uma pergunta muito boa. A resposta curta é que é o método abreviado antigo e será descontinuado. Usei-o na escola há mais de dez anos e raramente o vejo na prática. Aqui está a descrição mais concisa que consegui encontrar: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon
1

Um caso de uso é verificar se há registros duplicados em um banco de dados.

SELECT A.Id FROM My_Bookings A, My_Bookings B
WHERE A.Name = B.Name
AND A.Date = B.Date
AND A.Id != B.Id
Steven Stewart-Gallus
fonte
É muito mais rápido usar GROUP BY e a cláusula HAVING para localizar duplicatas. SELECIONE nome, e-mail, COUNT ( ) FROM My_Bookings GRUPO POR nome, data HAVING COUNT ( )> 1
George K
@GeorgeK True. Suponho que isso seja necessário apenas para uma correspondência difusa (além do agrupamento por TRIM (LOWER (Name))) e não para igualdade estrita.
Steven Stewart-Gallus
1

A auto-junção é útil quando você precisa avaliar os dados da tabela com ela mesma. O que significa que ele correlacionará as linhas da mesma tabela.

Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName

Por exemplo, queremos encontrar os nomes dos funcionários cuja designação inicial é igual à designação atual. Podemos resolver isso usando self join da seguinte maneira.

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId
Sumanth Varada
fonte
0

É o equivalente do banco de dados a uma lista / árvore vinculada, onde uma linha contém uma referência de alguma forma a outra linha.

Não licenciado
fonte
Na verdade, dado que mais de uma linha pode fazer referência a um "pai", ela também pode ser uma árvore, como no exemplo frequentemente citado de funcionário-> gerente.
NVRAM
Eu estava apenas tentando uma analogia simples, mas sim, uma árvore poderia funcionar também.
licenciado em
-4

Aqui está a explicação de self join em termos leigos. A autojunção não é um tipo diferente de união. Se você entendeu outros tipos de junções (Inner, Outer e Cross Joins), então a self join deve ser direta. Em INNER, OUTER e CROSS JOINS, você junta 2 ou mais tabelas diferentes. No entanto, em self join, você se junta à mesma mesa com ela mesma. Aqui, não temos 2 tabelas diferentes, mas tratamos a mesma tabela como uma tabela diferente usando apelidos de tabela. Se isso ainda não está claro, eu recomendo assistir os seguintes vídeos do youtube.

Auto-junte-se com um exemplo

user1472512
fonte