Spiegazione dei self-join


87

Non capisco la necessità di auto-join. Qualcuno può spiegarmeli?

Un semplice esempio sarebbe molto utile.

Risposte:


99

Puoi visualizzare l'auto-join come due tabelle identiche. Ma nella normalizzazione, non puoi creare due copie della tabella, quindi simuli semplicemente di avere due tabelle con l'auto collegamento.

Supponi di avere due tabelle:

tavolo emp1

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

tavolo emp2

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

Ora, se vuoi ottenere il nome di ogni dipendente con i nomi del suo capo:

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

Che produrrà la seguente tabella:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF

1
In questo esempio, non riesco a capire chi è il capo. Anche se l'esperienza è buona e facile da capire.
MAC

2
left joinPenso che sarebbe meglio non tralasciare il dipendente (o capo) che non ha un capo; il miglior cane!
Rockin4Life33

Dovrebbe essere da emp c1 invece di emp1 c1? @pointlesspolitics
Rohit Singh

22

È abbastanza comune quando hai una tabella che fa riferimento a se stessa. Esempio: una tabella dei dipendenti in cui ogni dipendente può avere un manager e si desidera elencare tutti i dipendenti e il nome del loro manager.

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

18

Un self join è l'unione di un tavolo con se stesso.

Un caso d'uso comune è quando la tabella memorizza entità (record) che hanno una relazione gerarchica tra di loro . Ad esempio una tabella contenente le informazioni sulla persona (Nome, Data di nascita, Indirizzo ...) e comprendente una colonna in cui è incluso l'ID del Padre (e / o della madre). Quindi con una piccola query come

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

possiamo ottenere informazioni sia sul bambino che sul padre (e sulla madre, con una seconda autoadesione ecc. e persino sui nonni, ecc.) nella stessa query.


5

Supponiamo che tu abbia un tavolo users, allestito in questo modo:

  • ID utente
  • nome utente
  • ID del manager dell'utente

In questa situazione, se si desidera estrarre sia le informazioni dell'utente che quelle del manager in una query, è possibile eseguire questa operazione:

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

4

Sono utili se la tua tabella è autoreferenziale. Ad esempio, per una tabella di pagine, ogni pagina può avere un collegamento nexte previous. Questi sarebbero gli ID di altre pagine nella stessa tabella. Se a un certo punto vuoi ottenere una tripla di pagine successive, faresti due auto-join sulle colonne nexte previouscon la stessa idcolonna della tabella .


4

Immagina una tabella chiamata Employeecome descritto di seguito. Tutti i dipendenti hanno un manager che è anche un dipendente (forse ad eccezione del CEO, il cui manager_id sarebbe nullo)

Table (Employee): 

int id,
varchar name,
int manager_id

È quindi possibile utilizzare la seguente selezione per trovare tutti i dipendenti e i loro manager:

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id

4

Senza la possibilità per una tabella di fare riferimento a se stessa, dovremmo creare tante tabelle per i livelli gerarchici quanti sono i livelli nella gerarchia. Ma poiché questa funzionalità è disponibile, unisci la tabella a se stessa e sql la tratta come due tabelle separate, quindi tutto è archiviato in un unico posto.


ma ora (si spera) capisci cosa accadrebbe se l'autoreferenzialità non fosse disponibile.
Eugene

4

Oltre alle risposte sopra menzionate (che sono molto ben spiegate), vorrei aggiungere un esempio in modo che l'uso di Self Join possa essere facilmente mostrato. Supponiamo di avere una tabella denominata CUSTOMERS che ha i seguenti attributi: CustomerID, CustomerName, ContactName, City, Country. Ora vuoi elencare tutti quelli che provengono dalla "stessa città". Dovrai pensare a una replica di questa tabella in modo che possiamo unirci sulla base di CITY. La query seguente mostrerà chiaramente cosa 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;

3
+1 Questa risposta è molto importante perché ci sono così tante domande SQL su SO a cui la risposta è "usa un self join", che le persone tendono a non vedere quando non hanno un riferimento esplicito (gerarchico).
JimmyB

1
Anche se questa è una copia della pasta di w3schools, penso che la risposta sopra non spieghi l'auto-join ma l'interno-join che è diverso.
George K

3

Ci sono molte risposte corrette qui, ma c'è una variazione che è ugualmente corretta. È possibile inserire le condizioni di join nell'istruzione di join anziché nella clausola 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

Tieni presente che a volte vuoi e1.manager_id> e2.id

Il vantaggio di conoscere entrambi gli scenari è che a volte hai un sacco di condizioni WHERE o JOIN e vuoi inserire le tue condizioni di auto join nell'altra clausola per mantenere il tuo codice leggibile.

Nessuno ha affrontato ciò che accade quando un dipendente non ha un manager. Eh? Non sono inclusi nel set di risultati. E se si desidera includere dipendenti che non hanno manager ma non si desidera restituire combinazioni errate?

Prova questo cucciolo;

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

1
Hm, nel cucciolo, perché ti unisci a "maggiore di" invece di "uguale"?
Marcel

1
Ciao. Ho visto che alcuni esempi usano "FROM xxx, yyy WHERE" e altri "FROM xxx JOIN yyy WHERE". Potresti spiegare la differenza, per favore?
skan

@Skan Questa è davvero una bella domanda. La risposta breve è che è il vecchio metodo abbreviato e sarà deprecato. L'ho usato a scuola più di dieci anni fa e raramente lo vedo in pratica. Ecco la descrizione più concisa che ho trovato: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon

1

Un caso d'uso è il controllo di record duplicati in un database.

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

È molto più veloce usare una clausola GROUP BY e a HAVING per trovare i duplicati. SELEZIONA nome, email, COUNT ( ) FROM My_Bookings GROUP PER nome, data HAVING COUNT ( )> 1
George K

@GeorgeK True. Suppongo che questo sia necessario solo per una corrispondenza fuzzy (oltre al raggruppamento per TRIM (LOWER (Name))) e non per l'uguaglianza rigorosa.
Molossus Spondee

1

L'auto-join è utile quando devi valutare i dati della tabella con se stessa. Ciò significa che correlerà le righe della stessa tabella.

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

Ad esempio, vogliamo trovare i nomi dei dipendenti la cui designazione iniziale è uguale alla designazione corrente. Possiamo risolvere questo problema usando l'auto join nel modo seguente.

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId

0

È l'equivalente del database di un elenco / albero collegato, in cui una riga contiene un riferimento in qualche modo a un'altra riga.


In realtà, dato che più di una riga può fare riferimento a un "genitore", può anche essere un albero, come nel citato esempio di dipendente-> manager.
NVRAM

Stavo solo cercando una semplice analogia, ma sì, anche un albero potrebbe funzionare.
affettato

-4

Ecco l'esaplanazione del self join in termini profani. L'auto join non è un tipo diverso di join. Se hai compreso altri tipi di join (Inner, Outer e Cross Joins), l'auto join dovrebbe essere semplice. In INNER, OUTER e CROSS JOINS, ti unisci a 2 o più tavoli diversi. Tuttavia, in te stesso ti unisci allo stesso tavolo con se stesso. Qui, non abbiamo 2 tabelle diverse, ma trattiamo la stessa tabella come una tabella diversa utilizzando gli alias di tabella. Se questo non è ancora chiaro, consiglierei di guardare i seguenti video di YouTube.

Self Join con un esempio

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.