Qual è la differenza tra "INNER JOIN" e "OUTER JOIN"?


4672

Inoltre come si fa LEFT JOIN, RIGHT JOINe FULL JOINin forma in?


64
Delle risposte e dei commenti e dei loro riferimenti di seguito solo uno spiega in realtà come i diagrammi di Venn rappresentano gli operatori: L'area di intersezione del cerchio rappresenta l'insieme di righe in UN JOIN B. L'area unica di ciascun cerchio rappresenta l'insieme di righe che ottieni prendendo il suo le righe della tabella che non partecipano a A JOIN B e aggiungono le colonne univoche all'altra tabella tutte impostate su NULL. (E molti danno una vaga falsa corrispondenza dei circoli ad A e B.)
philipxy,

1
Passando dalle risposte basate sulla teoria di seguito, a un'applicazione del mondo reale: lavoro spesso con i dati degli esperimenti, eseguendo benchmark sulla progettazione di processori. Spesso desidero confrontare i risultati tra 2 o più opzioni hardware. INNER JOIN significa che vedo solo i benchmark eseguiti correttamente in tutti gli esperimenti; OUTER JOIN significa che posso vedere tutti gli esperimenti, compresi quelli che non sono stati eseguiti su alcune configurazioni. È importante vedere i fallimenti in tali esperimenti, così come i successi. Abbastanza importante che ho scritto PerlSQL per ottenere OUTER JOIN, quando mancava a molti RDBMS,
Krazy Glew il

4
Sono già state fornite molte risposte ma non ho visto questo tutorial menzionato. Se conosci i diagrammi di Venn, questo è un GRANDE tutorial: blog.codinghorror.com/a-visual-explanation-of-sql-joins Per me, è abbastanza conciso per essere una lettura veloce ma afferra ancora l'intero concetto e funziona tutto casi molto bene. Se non sai cosa sono i diagrammi di Venn, imparali. Impiega 5-10 minuti per farlo e ti aiuterà ogni volta che devi visualizzare il lavoro con i set e la gestione delle operazioni sui set.
DanteTheSmith

15
@DanteTheSmith No, che soffre degli stessi problemi dei diagrammi qui. Vedi il mio commento sopra la domanda e sotto quello stesso post sul blog: "Jeff ripudia il suo blog alcune pagine nei commenti". I diagrammi di Venn mostrano gli elementi negli insiemi. Basta provare a identificare esattamente quali sono gli insiemi e quali sono gli elementi in questi diagrammi. I set non sono le tabelle e gli elementi non sono le loro righe. Inoltre, è possibile unire due tabelle qualsiasi, quindi PK e FK sono irrelvant. Tutti fasulli. Stai facendo esattamente ciò che hanno fatto migliaia di altri: hai una vaga impressione che (erroneamente) presumi abbia senso.
Philipxy,

3
Chris, ti consiglio di leggere questo articolo: towardsdatascience.com/… ... e prendere in considerazione di cambiare la scelta della risposta accettata (forse quella con la generosità) in una risposta che non utilizza i diagrammi di Venn. La risposta attualmente accettata sta fuorviando troppe persone. Vi esorto a farlo per il bene della nostra comunità e la qualità della nostra base di conoscenze.
Colm Bhandal,

Risposte:


6115

Supponendo che ti unisci a colonne senza duplicati, il che è un caso molto comune:

  • Un'unione interna di A e B fornisce il risultato dell'intersezione A, ovvero la parte interna di un'intersezione del diagramma di Venn .

  • Un'unione esterna di A e B fornisce i risultati di un'unione B, ovvero le parti esterne di un'unione del diagramma di Venn.

Esempi

Supponiamo di avere due tabelle, ciascuna con una singola colonna e dati come segue:

A    B
-    -
1    3
2    4
3    5
4    6

Si noti che (1,2) sono univoci per A, (3,4) sono comuni e (5,6) sono univoci per B.

Join interno

Un join interno che utilizza una delle query equivalenti fornisce l'intersezione delle due tabelle, ovvero le due righe che hanno in comune.

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

Unione esterna sinistra

Un join esterno sinistro fornirà tutte le righe in A, oltre a tutte le righe comuni in 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

Unione esterna destra

Un join esterno destro fornirà tutte le righe in B, oltre a tutte le righe comuni in 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

Join esterno completo

Un join esterno completo ti darà l'unione di A e B, cioè tutte le righe in A e tutte le righe in B. Se qualcosa in A non ha un dato corrispondente in B, allora la parte B è nulla e viceversa 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

42
Sarebbe utile aumentare l'esempio aggiungendo un'altra riga nella tabella B con valore 4. Ciò mostrerà che i join interni non devono necessariamente trovarsi sullo stesso numero di righe.
softveda,

473
Una spiegazione eccellente, tuttavia, questa affermazione: un unione esterna di A e B fornisce i risultati di un'unione B, ovvero le parti esterne di un'unione del diagramma di Venn. non è formulato con precisione. Un join esterno fornirà i risultati di A interseca B oltre a uno dei seguenti: tutti A (join sinistro), tutti B (join destro) o tutti A e tutti B (join completo). Solo quest'ultimo scenario è davvero un'unione B. Tuttavia, una spiegazione ben scritta.
Thomas,

11
Ho ragione che FULL JOIN è un alias di FULL OUTER JOIN e LEFT JOIN è un alias di LEFT OUTER JOIN?
Damian,

3
si grande ed eccellente spiegazione. ma perché nella colonna b i valori non sono in ordine? cioè è 6,5 non come 5,6?
Ameer

7
@Ameer, grazie. Partecipare non garantisce un ordine, è necessario aggiungere una clausola ORDER BY.
Mark Harrison,

734

I diagrammi di Venn non lo fanno davvero per me.

Non mostrano alcuna distinzione tra un join incrociato e un join interno, ad esempio, o più in generale mostrano alcuna distinzione tra diversi tipi di predicato di join o forniscono una struttura per ragionare su come funzioneranno.

Non vi è alcun sostituto per comprendere l'elaborazione logica ed è relativamente semplice da afferrare comunque.

  1. Immagina un cross join.
  2. Valutare la onclausola rispetto a tutte le righe del passaggio 1 mantenendo quelle in cui il predicato valutatrue
  3. (Solo per i join esterni) aggiungere nuovamente tutte le righe esterne che sono state perse nel passaggio 2.

(NB: in pratica, Query Optimizer può trovare modi più efficienti di eseguire la query rispetto alla descrizione puramente logica sopra, ma il risultato finale deve essere lo stesso)

Inizierò con una versione animata di un join esterno completo . Segue ulteriore spiegazione.

inserisci qui la descrizione dell'immagine


Spiegazione

Tabelle di origine

inserisci qui la descrizione del link

Prima di tutto inizia con un CROSS JOIN(prodotto cartesiano AKA). Questo non ha una ONclausola e restituisce semplicemente ogni combinazione di righe dalle due tabelle.

SELEZIONA A.Colore, B.Colore DA UN CROSS JOIN B

inserisci qui la descrizione del link

I join interni ed esterni hanno un predicato della clausola "ON".

  • Inner Join. Valutare la condizione nella clausola "ON" per tutte le righe nel risultato del join incrociato. Se vero restituisce la riga unita. Altrimenti scartalo.
  • Join esterno sinistro. Lo stesso del join interno, quindi, per tutte le righe nella tabella di sinistra che non corrispondevano a nulla restituite con valori NULL per le colonne della tabella di destra.
  • Join esterno destro. Lo stesso del join interno, quindi, per tutte le righe nella tabella di destra che non corrispondevano a nulla, restituiscile con valori NULL per le colonne della tabella di sinistra.
  • Join esterno completo. Come il join interno, quindi conserva le righe non corrispondenti a sinistra come nel join esterno sinistro e le righe non corrispondenti a destra come nel join esterno destro.

Qualche esempio

SELEZIONA A.Colore, B.Colore DA UN INTERNO UNISCI B SU A.Colore = B.Colore

Quanto sopra è il classico equi join.

Inner Join

Versione animata

inserisci qui la descrizione dell'immagine

SELEZIONA A.Colore, B.Colore DA UN INTERNO UNISCI B SU A.Colore NON IN ('Verde', 'Blu')

La condizione di join interno non deve necessariamente essere una condizione di uguaglianza e non deve necessariamente fare riferimento a colonne di entrambe (o persino di entrambe) delle tabelle. La valutazione A.Colour NOT IN ('Green','Blue')su ciascuna riga del cross join restituisce.

interno 2

SELEZIONA A.Colore, B.Colore DA UN INTERNO UNISCI B SU 1 = 1

La condizione di join viene valutata come vera per tutte le righe nel risultato del join incrociato, quindi è uguale a un join incrociato. Non ripeterò di nuovo l'immagine delle 16 file.

SELEZIONA A.Colore, B.Colore DA A SINISTRA ESTERNO UNISCITI B SU A.Colore = B.Colore

I join esterni vengono logicamente valutati allo stesso modo dei join interni, tranne per il fatto che se una riga della tabella di sinistra (per un'unione di sinistra) non si unisce a nessuna riga della tabella di destra, viene preservata nel risultato con i NULLvalori per colonne di destra.

LOJ

SELEZIONA A.Colore, B.Colore DA A SINISTRA ESTERNO UNISCITI B SU A.Colore = B.Colore DOVE B.Colore È NULL

Questo limita semplicemente il risultato precedente per restituire solo le righe dove B.Colour IS NULL. In questo caso particolare saranno le righe che sono state conservate in quanto non avevano corrispondenza nella tabella di destra e la query restituisce la singola riga rossa non corrispondente nella tabella B. Questo è noto come anti semi join.

È importante selezionare una colonna per il IS NULLtest che non sia nullable o per la quale la condizione di join garantisce che eventuali NULLvalori vengano esclusi affinché questo modello funzioni correttamente ed eviti di riportare le righe che risultano avere un NULLvalore per quello colonna oltre alle righe non corrispondenti.

loj è nullo

SELEZIONA A.Colore, B.Colore DA A DESTRA ESTERNO UNISCITI B SU A.Colore = B.Colore

I join esterni di destra funzionano in modo simile ai join esterni di sinistra, tranne per il fatto che mantengono le righe non corrispondenti dalla tabella di destra e null estendono le colonne di sinistra.

ROJ

SELEZIONA A.Colore, B.Colore DA UN COMPLETO ESTERNO UNISCITI B SU A.Colore = B.Colore

I join esterni completi combinano il comportamento dei join sinistro e destro e preservano le righe non corrispondenti dalle tabelle sinistra e destra.

UFG

SELEZIONA A.Colore, B.Colore DA UN COMPLETO ESTERNO UNISCITI B SU 1 = 0

Nessuna riga nell'unione incrociata corrisponde al 1=0predicato. Tutte le righe da entrambi i lati vengono conservate utilizzando le normali regole di join esterne con NULL nelle colonne della tabella sull'altro lato.

FOJ 2

SELEZIONA COALESCE (A.Colore, B.Colore) COME Colore DA UN ESTERNO COMPLETO UNISCI B SU 1 = 0

Con una modifica minore alla query precedente si potrebbe simulare una UNION ALLdelle due tabelle.

UNION ALL

SELEZIONA A.Colore, B.Colore DA A SINISTRA ESTERNO UNISCITI B SU A.Colore = B.Colore DOVE B.Colore = 'Verde'

Si noti che la WHEREclausola (se presente) viene eseguita logicamente dopo il join. Un errore comune è quello di eseguire un join esterno sinistro e quindi includere una clausola WHERE con una condizione sulla tabella destra che finisce escludendo le righe non corrispondenti. Quanto sopra finisce per eseguire il join esterno ...

LOJ

... E poi viene eseguita la clausola "Where". NULL= 'Green'non valuta come vero, quindi la riga conservata dal join esterno finisce scartata (insieme a quella blu) convertendo efficacemente il join in uno interno.

LOJtoInner

Se l'intenzione fosse quella di includere solo le righe da B in cui il colore è verde e tutte le righe da A indipendentemente dalla sintassi corretta sarebbe

SELEZIONA A.Colore, B.Colore DA A SINISTRA ESTERNO UNISCITI B SU A.Colore = B.Colore E B.Colore = 'Verde'

inserisci qui la descrizione dell'immagine

SQL Fiddle

Vedi questi esempi eseguiti dal vivo su SQLFiddle.com .


46
Dirò che mentre questo non funziona per me quasi come per i diagrammi di Venn, apprezzo il fatto che le persone varino e apprendano in modo diverso e questa è una spiegazione molto ben presentata diversa da qualsiasi che abbia mai visto prima, quindi supporto @ypercube in assegnazione dei punti bonus. Anche un buon lavoro che spiega la differenza di mettere condizioni aggiuntive nella clausola JOIN rispetto alla clausola WHERE. Complimenti a te, Martin Smith.
Vecchio Pro

22
@OldPro I diagrammi di Venn sono OK per quanto vanno, suppongo, ma tacciono su come rappresentare un cross join o per differenziare un tipo di predicato di join come equi join da un altro. Il modello mentale di valutazione del predicato di join su ciascuna riga del risultato del join incrociato quindi l'aggiunta di nuovo in righe senza eguali se un join esterno e infine la valutazione di dove funziona meglio per me.
Martin Smith,

18
I diagrammi di Venn sono utili per rappresentare unioni, intersezioni e differenze, ma non unioni. Hanno un valore educativo minore per join molto semplici, ovvero join in cui la condizione di join è su colonne uniche.
ypercubeᵀᴹ

12
@Arth - No, ti sbagli. SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 questo è qualcosa che i diagrammi di Venn non possono illustrare.
Martin Smith

7
@MartinSmith Wow, sono d'accordo, mi sbaglio totalmente! Troppo abituato a lavorare con one-to-manys .. grazie per la correzione.
Arth

188

I join vengono utilizzati per combinare i dati di due tabelle, con il risultato che è una nuova tabella temporanea. I join vengono eseguiti in base a qualcosa chiamato predicato, che specifica la condizione da utilizzare per eseguire un join. La differenza tra un join interno e un join esterno è che un join interno restituirà solo le righe che corrispondono effettivamente in base al predicato del join. Ad esempio: prendiamo in considerazione la tabella Dipendente e Località:

inserisci qui la descrizione dell'immagine

Join interno: - Il join interno crea una nuova tabella dei risultati combinando i valori di colonna di due tabelle ( Employee e Location ) in base al predicato di join. La query confronta ogni riga del Dipendente con ciascuna riga di Location per trovare tutte le coppie di righe che soddisfano il predicato di join. Quando il predicato di join viene soddisfatto abbinando valori non NULL, i valori di colonna per ciascuna coppia di righe di Employee e Location corrispondenti vengono combinati in una riga di risultato. Ecco come apparirà l'SQL per un join interno:

select  * from employee inner join location on employee.empID = location.empID
OR
select  * from employee, location where employee.empID = location.empID

Ora, ecco come sarebbe il risultato dell'esecuzione di quell'SQL: inserisci qui la descrizione dell'immagine

Join esterno: - Un join esterno non richiede che ogni record nelle due tabelle unite abbia un record corrispondente. La tabella unita conserva ogni record, anche se non esiste nessun altro record corrispondente. I join esterni si suddividono ulteriormente in join esterni a sinistra e join esterni a destra, a seconda delle righe della tabella mantenute (sinistra o destra).

Join esterno sinistro: - Il risultato di un join esterno sinistro (o semplicemente un join sinistro) per le tabelle Employee e Location contiene sempre tutti i record della tabella "left" ( Employee ), anche se la condizione di join non trova alcun record corrispondente in la tabella "giusta" ( posizione ). Ecco come sarebbe l'SQL per un join esterno sinistro, usando le tabelle sopra:

select  * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional

Ora, ecco come sarebbe il risultato dell'esecuzione di questo SQL: inserisci qui la descrizione dell'immagine

Unione esterna destra: - Un'unione esterna destra (o unione destra) ricorda da vicino un'unione esterna sinistra, tranne per il trattamento delle tabelle invertito. Ogni riga della tabella "destra" ( Posizione ) apparirà nella tabella unita almeno una volta. Se non esiste alcuna riga corrispondente dalla tabella "sinistra" ( Dipendente ), NULL apparirà in colonne da Dipendente per quei record che non hanno corrispondenza in Posizione . Ecco come appare l'SQL:

select * from employee right outer join location  on employee.empID = location.empID;
//Use of outer keyword is optional

Usando le tabelle sopra, possiamo mostrare come sarebbe il set di risultati di un join esterno destro:

inserisci qui la descrizione dell'immagine

Join esterni completi : - Join esterni completi o Join completi per conservare le informazioni non corrispondenti includendo le righe non corrispondenti nei risultati di un join, utilizzare un join esterno completo. Include tutte le righe di entrambe le tabelle, indipendentemente dal fatto che l'altra tabella abbia o meno un valore corrispondente.

Fonte immagine

Manuale di riferimento di MySQL 8.0 - Partecipa alla sintassi

Operazioni di join Oracle


3
migliore risposta finora, sintassi alternativa - questo è quello che stavo cercando, grazie!
Joey,

1
I diagrammi di Venn sono etichettati erroneamente. Vedi i miei commenti sulla domanda e altre risposte. Anche la maggior parte di questa lingua è scarsa. Ad esempio: "Quando il predicato di join viene soddisfatto dalla corrispondenza di valori non NULL, i valori di colonna per ciascuna coppia di righe di Employee e Location corrispondenti vengono combinati in una riga di risultato." No, non "Quando il predicato join è soddisfatto abbinando valori non NULL". I valori nelle righe non contano se la condizione nel suo insieme è vera o falsa. Alcuni valori potrebbero essere NULL per una condizione vera.
Philipxy,

Sebbene non esplicitamente dichiarato, i diagrammi in questo sono diagrammi di Venn. I diagrammi di Venn non sono, in generale, la corretta caratterizzazione matematica di un join. Suggerisco di rimuovere i diagrammi di Venn.
Colm Bhandal

@ColmBhandal: rimosso i diagrammi di Venn
ajitksharma

Si prega di utilizzare il testo, non immagini / collegamenti, per il testo, inclusi tabelle ed ERD . Usa le immagini solo per ciò che non può essere espresso come testo o per aumentare il testo. Non è possibile cercare o tagliare e incollare le immagini. Includi una legenda / chiave e una spiegazione con un'immagine.
philipxy

133

Inner Join

Recupera solo le righe corrispondenti, ovvero A intersect B.

Inserisci qui la descrizione dell'immagine

SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Join esterno sinistro

Seleziona tutti i record dalla prima tabella e tutti i record nella seconda tabella che corrispondono alle chiavi unite.

Inserisci qui la descrizione dell'immagine

SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Join esterno completo

Seleziona tutti i record dalla seconda tabella e tutti i record nella prima tabella che corrispondono alle chiavi unite.

Inserisci qui la descrizione dell'immagine

SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Riferimenti


14
Qual è il nome dello strumento? Trovo che sia interessante in quanto mostra il numero di righe e diagrammi di
Venn

2
@GrijeshChauhan Sì, ma puoi provare a eseguirlo usando il vino .
Tushar Gupta - curioustushar,

2
Ohh! sì, ho usato SQLyog usando il vino .. c'è anche PlayOnLinux
Grijesh Chauhan,

1
Il tuo testo è poco chiaro e sbagliato. Le "sole righe abbinate" sono righe della giunzione incrociata di A e B e ciò che viene recuperato (una giuntura interna B) non è una intersezione B ma (una giuntura sinistra B) si intersecano (una giuntura destra B). Le righe "selezionate" non provengono da A e B, provengono da A, uniscono B e da valori null-null delle righe da A e B.
philipxy

@ TusharGupta-curioustushar dovresti includere le "Tabelle utilizzate per esempi SQL"
Manuel Jordan,

112

In parole semplici:

Un'unione interiore recupera solo le righe corrispondenti.

Considerando che un join esterno recupera le righe corrispondenti da una tabella e tutte le righe nell'altra tabella .... il risultato dipende da quale si sta utilizzando:

  • Sinistra : righe corrispondenti nella tabella di destra e tutte le righe nella tabella di sinistra

  • Destra : righe corrispondenti nella tabella di sinistra e tutte le righe nella tabella di destra o

  • Completo : tutte le righe in tutte le tabelle. Non importa se c'è una partita o no


1
@nomen Non che questa risposta sia indirizzata, ma INNER JOIN è un incrocio e FULL OUTER JOIN è l'UNIONE corrispondente se gli insiemi / cerchi sinistro e destro contengono le righe di (rispettivamente) LEFT & RIGHT join. PS Questa risposta non è chiara sulle righe in input vs output. Confonde "nella tabella sinistra / destra" con "ha una parte sinistra / destra nella sinistra / destra" e usa "riga abbinata" vs "all" per indicare la riga estesa per riga dall'altra tabella vs da valori null.
Philipxy,

104

Un join interno mostra le righe solo se è presente un record corrispondente sull'altro lato (destro) del join.

Un join esterno (sinistro) mostra le righe per ciascun record sul lato sinistro, anche se non vi sono righe corrispondenti sull'altro lato (destro) del join. Se non ci sono righe corrispondenti, le colonne per l'altro lato (destro) mostreranno NULL.


82

I join interni richiedono l'esistenza di un record con un ID correlato nella tabella unita.

I join esterni restituiranno i record per il lato sinistro anche se non esiste nulla per il lato destro.

Ad esempio, hai una tabella Orders e OrderDetails. Sono collegati da un "OrderID".

Ordini

  • ID ordine
  • Nome del cliente

OrderDetails

  • OrderDetailID
  • ID ordine
  • Nome del prodotto
  • Quantità
  • Prezzo

La richiesta

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
 INNER JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID

restituirà solo gli ordini che hanno anche qualcosa nella tabella OrderDetails.

Se lo cambi in ESTERNO SINISTRA UNISCITI

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
  LEFT JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID

quindi restituirà i record dalla tabella Ordini anche se non hanno record OrderDetails.

Puoi usarlo per trovare ordini che non hanno alcun OrderDetails che indica un possibile ordine orfano aggiungendo una clausola where WHERE OrderDetails.OrderID IS NULL.


1
Apprezzo l'esempio semplice ma realistico. Ho cambiato una richiesta simile 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 ASCa 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) con successo. Non ero sicuro delle condizioni aggiuntive, si mescolano bene ...
PhiLho

68

In parole semplici:

Join interno -> Prendi SOLO i record comuni dalle tabelle padre e figlio DOVE la chiave primaria della tabella padre corrisponde alla chiave esterna nella tabella figlio.

Join sinistro ->

pseudo codice

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.
    }
  }

Unisciti a destra : esattamente opposto rispetto al join sinistro. Inserisci il nome della tabella in LEFT JOIN sul lato destro in Right join, otterrai lo stesso output di LEFT JOIN.

Join esterno : mostra tutti i record in entrambe le tabelleNo matter what . Se i record nella tabella di sinistra non corrispondono alla tabella di destra in base alla chiave primaria, Forieign, utilizzare il valore NULL come risultato del join.

Esempio :

Esempio

Supponiamo ora per 2 tavoli

1.employees , 2.phone_numbers_employees

employees : id , name 

phone_numbers_employees : id , phone_num , emp_id   

Qui, la tabella degli impiegati è la tabella principale, phone_numbers_employees è la tabella figlio (contiene emp_idcome chiave esterna che si collega employee.idquindi la sua tabella figlio).

Join interni

Prendi i record di 2 tabelle SOLO SE La chiave primaria della tabella degli impiegati (il suo ID) corrisponde alla chiave esterna della tabella figlio phone_numbers_employees (emp_id) .

Quindi la query sarebbe:

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;

Qui prendi solo le righe corrispondenti sulla chiave primaria = chiave esterna come spiegato sopra. Qui le righe non corrispondenti sulla chiave primaria = chiave esterna vengono saltate come risultato del join.

Join di sinistra :

Il join sinistro mantiene tutte le righe della tabella di sinistra, indipendentemente dal fatto che vi sia una riga corrispondente nella tabella di destra.

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;

Join esterni :

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;

Diagrammaticamente sembra:

Diagramma


4
Il risultato non ha nulla da fare (di per sé) con chiavi primarie / uniche / candidate e chiavi esterne. Il baviour può e deve essere descritto senza riferimento ad essi. Viene calcolato un cross join, quindi le righe che non corrispondono alla condizione ON vengono filtrate; inoltre per i join esterni le righe filtrate / senza eguali sono estese di NULL (per LEFT / RIGHT / FULL e incluse.
philipxy

Il presupposto che i join SQL corrispondano sempre a chiavi primarie / esterne sta portando a questo uso improprio dei diagrammi di Venn. Ti preghiamo di rivedere la tua risposta di conseguenza.
Colm Bhandal

58

Si utilizza INNER JOINper restituire tutte le righe da entrambe le tabelle in cui esiste una corrispondenza. cioè nella tabella risultante tutte le righe e le colonne avranno valori.

Nella OUTER JOINtabella risultante possono essere presenti colonne vuote. L'unione esterna può essere LEFTo RIGHT.

LEFT OUTER JOIN restituisce tutte le righe dalla prima tabella, anche se non vi sono corrispondenze nella seconda tabella.

RIGHT OUTER JOIN restituisce tutte le righe dalla seconda tabella, anche se non ci sono corrispondenze nella prima tabella.



54

INNER JOINrichiede almeno una corrispondenza nel confronto tra le due tabelle. Ad esempio, la tabella A e la tabella B che implica A ٨ B (intersezione A B).

LEFT OUTER JOIN e LEFT JOIN sono uguali. Fornisce tutti i record corrispondenti in entrambe le tabelle e tutte le possibilità della tabella di sinistra.

Allo stesso modo, RIGHT OUTER JOINe RIGHT JOINsono gli stessi. Fornisce tutti i record corrispondenti in entrambe le tabelle e tutte le possibilità della tabella giusta.

FULL JOINè la combinazione di LEFT OUTER JOINe RIGHT OUTER JOINsenza duplicazione.


43

La risposta è nel significato di ciascuno, quindi nei risultati.

Nota:
In SQLitenon c'è RIGHT OUTER JOINo FULL OUTER JOIN.
E anche dentro MySQLnon c'è FULL OUTER JOIN.

La mia risposta si basa sulla nota sopra .

Quando hai due tavoli come questi:

--[table1]               --[table2]
id | name                id | name
---+-------              ---+-------
1  | a1                  1  | a2
2  | b1                  3  | b2

CROSS JOIN / OUTER JOIN:
puoi avere tutti quei dati delle tabelle con CROSS JOINo semplicemente con ,questo:

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 si desidera aggiungere un filtro ai risultati sopra basati su una relazione come table1.id = table2.idè possibile utilizzare 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

LEFT [OUTER] JOIN:
Quando vuoi avere tutte le righe di una delle tabelle nel risultato sopra -con la stessa relazione- puoi usare LEFT JOIN:
(Per JOIN RIGHT basta cambiare il posto delle tabelle)

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

UNISCITI ESTERNI COMPLETI:
quando vuoi avere anche tutte le righe dell'altra tabella nei tuoi risultati puoi usare 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

Bene, in base alle tue necessità, scegli ognuna che copra le tue necessità;).


Puoi aggiungere alla tua nota che neanche full outer joinMySQL è presente .
Potashin,

35

Join interno.

Un join sta combinando le righe da due tabelle. Un join interno tenta di abbinare le due tabelle in base ai criteri specificati nella query e restituisce solo le righe corrispondenti. Se una riga della prima tabella nel join corrisponde a due righe nella seconda tabella, nei risultati verranno restituite due righe. Se c'è una riga nella prima tabella che non corrisponde a una riga nella seconda, non viene restituita; allo stesso modo, se c'è una riga nella seconda tabella che non corrisponde a una riga nella prima, non viene restituita.

Join esterno.

Un join sinistro tenta di trovare la corrispondenza tra le righe della prima tabella e le righe della seconda tabella. Se non riesce a trovare una corrispondenza, restituirà le colonne della prima tabella e lascerà vuote le colonne della seconda tabella (null).


28

inserisci qui la descrizione dell'immagine

  • INNER JOINjoin più tipico per due o più tabelle. Restituisce la corrispondenza dei dati su entrambi tabella ON chiave primaria e relazione forignkey.
  • OUTER JOINè uguale a INNER JOIN, ma include anche i NULLdati su ResultSet.
    • LEFT JOIN= INNER JOIN+ Dati ineguagliati della tabella di sinistra con Nullcorrispondenza sulla tabella di destra.
    • RIGHT JOIN= INNER JOIN+ Dati senza pari della tabella destra conNull corrispondenza sulla tabella di sinistra.
    • FULL JOIN= INNER JOIN+ Dati senza eguali su entrambe le tabelle destra e sinistra con Nullcorrispondenze.
  • Self join non è una parola chiave in SQL, quando una tabella fa riferimento a dati in sé noti come self join. Utilizzando INNER JOINe OUTER JOINpossiamo scrivere query di auto-join.

Per esempio:

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 

27

Non vedo molti dettagli sulle prestazioni e sull'ottimizzatore nelle altre risposte.

A volte è bene saperlo solo INNER JOIN è associativo, il che significa che l'ottimizzatore ha più possibilità di giocarci. Può riordinare l'ordine di join per renderlo più veloce mantenendo lo stesso risultato. L'ottimizzatore può utilizzare la maggior parte delle modalità di join.

Generalmente è una buona pratica provare a utilizzare al INNER JOINposto del diverso tipo di join. (Naturalmente se è possibile considerando il set di risultati attesi.)

Ci sono un paio di buoni esempi e spiegazioni qui su questo strano comportamento associativo:


4
Non può essere "buona pratica" utilizzare un tipo di join rispetto a un altro. Quale join si utilizza determina i dati desiderati. Se ne usi uno diverso, non sei corretto. Inoltre, in Oracle almeno questa risposta è completamente sbagliata. Sembra completamente sbagliato per tutto e non hai prove. Hai delle prove?
Ben,

1. Intendo provare a usare. Ho visto un sacco di gente che utilizzava LEFT OUTER unendosi ovunque senza una buona ragione. (Le colonne unite erano "non nulle"). In quei casi sarebbe sicuramente meglio usare i join INNER. 2. Ho aggiunto un link che spiega il comportamento non associativo meglio di quanto potessi.
Lajos Veres,

Come so INNER JOINè più lento che LEFT JOINnella maggior parte delle volte, e le persone possono usare LEFT JOINinvece di INNER JOINaggiungere un WHEREper rimuovere NULLrisultati imprevisti ;).
shA.t

Questi commenti mi hanno reso un po 'incerto. Perché pensi che INNERsia più lento?
Lajos Veres,

Dipende dal motore. gnu join, joinkeys, DB2, MySQL. Trappole di prestazioni abbondano, come la digitazione libera o un cast esplicito.
mckenzm,

26

Dopo aver criticato il tanto amato diagramma di Venn in rosso, ho pensato che fosse giusto pubblicare il mio tentativo.

Sebbene la risposta di @Martin Smith sia di gran lunga la migliore di questo gruppo, mostra solo la colonna chiave di ogni tabella, mentre penso che anche le colonne idealmente non chiave dovrebbero essere mostrate.

Il meglio che potrei fare nella mezz'ora consentita, non penso ancora che mostri adeguatamente che i valori null sono lì a causa dell'assenza di valori chiave TableBo che in OUTER JOINrealtà è un'unione piuttosto che un'unione:

inserisci qui la descrizione dell'immagine


2
La domanda sta chiedendo la differenza tra i join INNER e OUTER, ma non necessariamente lasciato lol esterno join
LearnByLeggi

@LearnByReading: la mia foto a destra è un join esterno destro, ovvero sostituisci TableA a LEFT OUTER JOIN TableB bconTableB B RIGHT OUTER JOIN TableA a
onedayquando il

26

L'algoritmo preciso per INNER JOIN, LEFT/RIGHT OUTER JOINsono i seguenti:

  1. Prendi ogni riga dalla prima tabella: a
  2. Considera tutte le righe della seconda tabella accanto: (a, b[i])
  3. Valuta la ON ...clausola rispetto a ciascuna coppia:ON( a, b[i] ) = true/false?
    • Quando la condizione truerestituisce, restituisce quella riga combinata (a, b[i]).
    • Quando raggiunge la fine della seconda tabella senza alcuna corrispondenza, si tratta Outer Joinquindi di restituire una coppia (virtuale) usando Nullper tutte le colonne dell'altra tabella: (a, Null)per il join esterno SINISTRA o il (Null, b)join esterno DESTRO. Questo per garantire che tutte le righe della prima tabella esistano nei risultati finali.

Nota: la condizione specificata nella ONclausola potrebbe essere qualsiasi cosa, non è necessario utilizzare le chiavi primarie (e non è necessario fare sempre riferimento alle colonne di entrambe le tabelle)! Per esempio:

Join interno vs. Join esterno sinistro


inserisci qui la descrizione dell'immagine

Nota: Join sinistro = Join esterno sinistro, Join destro = Join esterno destro.


20

Definizioni più semplici

Inner Join: restituisce i record corrispondenti da entrambe le tabelle.

Join esterno completo: restituisce i record corrispondenti e non corrispondenti di entrambe le tabelle con null per i record non corrispondenti di entrambe le tabelle .

Join esterno sinistro: restituisce i record corrispondenti e non corrispondenti solo dalla tabella sul lato sinistro .

Join esterno destro: restituisce i record corrispondenti e non corrispondenti solo dalla tabella sul lato destro .

In breve

Corrispondenza + sinistra senza corrispondenza + destra senza corrispondenza = unione esterna completa

Matched + Left Unmatched = Join esterno sinistro

Matched + Right Unmatched = Right Outer Join

Abbinato = Join interno


1
Questo è geniale e spiega perché il join non funziona come previsto per gli indici delle serie storiche. I timestamp a un secondo di distanza non hanno eguali.
yeliabsalohcin,

1
@yeliabsalohcin Non spieghi "come previsto" qui o "funziona" nel tuo commento alla domanda. È solo un malinteso personale inspiegabile che stranamente ti aspetti che gli altri abbiano. Se tratti le parole in modo sciatto quando leggi - interpretare erroneamente una scrittura chiara e / o accettando una scrittura poco chiara - come quando scrivi qui, puoi aspettarti di avere idee sbagliate. In effetti questa risposta come la maggior parte qui è poco chiara e sbagliata. "Inner Join: restituisce i record corrispondenti da entrambe le tabelle" è errato quando i set di colonne di input differiscono. Sta cercando di dire un certo qualcosa, ma non lo è . (Vedi la mia risposta).
philipxy,

9

In parole povere,

1. JOIN INNER O JOIN EQUI: restituisce il gruppo di risultati che corrisponde solo alla condizione in entrambe le tabelle.

2. OUTER JOIN: restituisce il set di risultati di tutti i valori da entrambe le tabelle anche se esiste una corrispondenza delle condizioni o meno.

3. JOIN SINISTRA: restituisce il set di risultati di tutti i valori dalla tabella a sinistra e solo le righe che corrispondono alla condizione nella tabella a destra.

4. JOIN DESTRO: restituisce il set di risultati di tutti i valori dalla tabella di destra e solo le righe che corrispondono alla condizione nella tabella di sinistra.

5. JOIN COMPLETO: Full Join e Full outer Join sono uguali.


5

Esistono principalmente 2 tipi principali di JOIN in SQL: [INTERNO e ESTERNO]


Esempi

Supponiamo di avere due tabelle, ciascuna con una singola colonna e dati come segue:

A    B
-    -
1    3
2    4
3    5
4    6
7
8

Si noti che (1,2,7,8) sono unici per A, (3,4) sono comuni e (5,6) sono unici per B.



  • (INTERNO) ISCRIVITI :

La parola chiave INNER JOIN seleziona tutte le righe da entrambe le tabelle purché la condizione soddisfi. Questa parola chiave creerà il set di risultati combinando tutte le righe di entrambe le tabelle in cui la condizione soddisfa, ovvero il valore del campo comune sarà lo stesso.

UNIONE INTERNA

select * from a INNER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b;

Risultato:

a | b
--+--
3 | 3
4 | 4


  • SINISTRA (ESTERNO) ISCRIVITI :

Questo join restituisce tutte le righe della tabella sul lato sinistro del join e le righe corrispondenti per la tabella sul lato destro del join. Le righe per le quali non esiste una riga corrispondente sul lato destro, il set di risultati conterrà null. LEFT JOIN è anche noto come LEFT OUTER JOIN.

ISCRIVITI A SINISTRA / ISCRIVITI A SINISTRA ESTERNO

select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b(+);

Risultato:

a |  b
--+-----
1 | null
2 | null
3 |    3
4 |    4
7 | null
8 | null


  • RIGHT (OUTER) JOIN : restituisce tutti i record dalla tabella di destra e i record corrispondenti dalla tabella di sinistra

UNIONE DESTRA / UNIONE ESTERNA DESTRA

select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a(+) = b.b;

Risultato:

a    |  b
-----+----
3    |  3
4    |  4
null |  5
null |  6


  • FULL (ESTERNO) ISCRIVITI :

    FULL JOIN crea il set di risultati combinando il risultato di LEFT JOIN e RIGHT JOIN. Il set di risultati conterrà tutte le righe di entrambe le tabelle. Le righe per le quali non esiste corrispondenza, il set di risultati conterrà valori NULL.

FULL JOIN / FULL OUTER JOIN

select * from a FULL OUTER JOIN b on a.a = b.b;

Risultato:

 a   |  b
-----+-----
   1 | null
   2 | null
   3 |    3
   4 |    4
null |    6
null |    5
   7 | null
   8 | null

1
I diagrammi di Venn non sono sufficienti per descrivere i join SQL nel caso generale. I join SQL non devono necessariamente abbinare le righe tra le tabelle uno a uno, ad esempio utilizzando la chiave esterna rispetto alla chiave primaria.
Colm Bhandal

Come si uniscono 2 tavoli senza abbinare la riga? È necessario disporre di una chiave primaria o esterna di colonna o di un campo comune per poter eseguire il join. Mi chiedo perché hai votato in negativo questa risposta. E il diagramma di Venn è la fonte per spiegare come funziona SQL JOIN. Hai qualche esempio migliore per rappresentare i join? In caso contrario, ti preghiamo di votarlo, in modo che le persone ottengano soluzioni migliori. Grazie.
Mayur

Sei tu a mettere gli schemi nel post. Qual è la legenda dei diagrammi? - Quali sono gli elementi di ogni set? E che dire del fatto che i tavoli sono borse non set? Non dici. Una cosa di cui non sono insiemi sono le righe di A e B per le etichette. Vedi i miei commenti sui post in questa pagina. Questo post ripete semplicemente alla cieca un uso errato visto altrove ma non compreso o messo in discussione. Anche le cose che dici nel testo qui sono poco chiare e sbagliate. Inoltre non aggiunge nulla alle molte risposte già qui. (Anche se quasi tutti sono abbastanza poveri.) PS Per favore chiarisci tramite le modifiche, non i commenti.
philipxy

Gli FK non sono necessari per partecipare o eseguire query. Ogni 2 tabelle possono essere unite in qualsiasi condizione che coinvolga le loro colonne e indipendentemente da eventuali vincoli, trigger o asserzioni.
philipxy

3
  • Join interno : un join interno che utilizza una delle query equivalenti fornisce l'intersezione delle due tabelle , ovvero le due righe che hanno in comune.

  • Join esterno sinistro : un join esterno sinistro fornirà tutte le righe in A, oltre a tutte le righe comuni in B.

  • Join esterno completo : un join esterno completo fornisce l'unione di A e B, ovvero tutte le righe in A e tutte le righe in B. Se qualcosa in A non ha un dato corrispondente in B, la porzione B è null e viceversa


1
Questo è sia sbagliato che poco chiaro. Unire non è un'intersezione a meno che le tabelle non abbiano le stesse colonne. I join esterni non hanno righe da A o B a meno che non abbiano le stesse colonne, nel qual caso non vengono aggiunti null. Stai cercando di dire qualcosa, ma non lo stai dicendo. Non stai spiegando correttamente o chiaramente.
Philipxy,

@philipxy: in disaccordo sulla tua affermazione Join is not an intersection unless the tables have the same columnsNo. Puoi unire tutte le colonne che desideri e se il valore corrisponde, si uniranno.
SuicideSheep,

Quel commento non è chiaro come la tua risposta. (Suppongo che potresti pensare qualcosa del genere, l'insieme dei valori di sottotitolo per le colonne comuni del risultato è l'intersezione degli insiemi di valori di sottotitolo per le colonne comuni di ciascuno degli input; ma non è quello che hai scritto. non sono chiari.)
philipxy,

Ciò che intendevo dire era che il join è solo un'intersezione di input quando si tratta di un join interno naturale di input con le stesse colonne. Stai usando le parole "intersezione" e "unione" in modo errato.
Philipxy,

3

1. Inner Join: chiamato anche come Join. Restituisce le righe presenti sia nella tabella di sinistra, sia nella tabella di destra solo se esiste una corrispondenza . Altrimenti, restituisce zero record.

Esempio:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
INNER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

output1

2. Join esterno completo: chiamato anche Full Join. Restituisce tutte le righe presenti nella tabella di sinistra e nella tabella di destra.

Esempio:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
FULL OUTER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

Output2

3. Join esterno sinistro: Join o semplicemente chiamato come Join sinistro. Restituisce tutte le righe presenti nella tabella di sinistra e le righe corrispondenti dalla tabella di destra (se presenti).

4. Join esterno destro: chiamato anche come join destro. Restituisce le righe corrispondenti dalla tabella di sinistra (se presente) e tutte le righe presenti nella tabella di destra.

si unisce

Vantaggi dei join

  1. Esegue più velocemente.

2
Questo è corretto solo quando le tabelle hanno lo stesso set di colonne. (Confonde l'unione interna con l'intersezione e l'unione completa con l'unione.) Anche "corrispondenza" non è definito. Leggi i miei altri commenti.
philipxy,

2

Considera di seguito 2 tabelle:

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

Dipartimento

deptid  name
1       IT
2       Accounts
3       Security
4       HR
5       R&D

Inner Join:

Principalmente scritto come JOIN nelle query sql. Restituisce solo i record corrispondenti tra le tabelle.

Scopri tutti i dipendenti e i nomi dei loro dipartimenti:

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

Come vedete sopra, Josenon viene stampata dalla EMP nell'output quanto di dept_id 6non trova una corrispondenza nella tabella dipartimento. Allo stesso modo, HRe le R&Drighe non vengono stampate dalla tabella Department poiché non hanno trovato una corrispondenza nella tabella Emp.

Quindi, INNER JOIN o semplicemente JOIN, restituisce solo le righe corrispondenti.

ISCRIVITI A SINISTRA:

Ciò restituisce tutti i record dalla tabella SINISTRA e solo i record corrispondenti dalla tabella DESTRA.

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    

Pertanto, se si osserva l'output sopra riportato, tutti i record della tabella LEFT (Emp) vengono stampati con solo i record corrispondenti della tabella DESTRA.

HRe le R&Drighe non vengono stampate dalla tabella Department poiché non hanno trovato una corrispondenza nella tabella Emp su dept_id.

Quindi, SINISTRA SINISTRA restituisce TUTTE le righe dalla tabella sinistra e solo le righe corrispondenti dalla tabella DESTRA.

Puoi anche controllare DEMO qui .


2

L'idea generale

Si prega di consultare la risposta di Martin Smith per una migliore spiegazione e spiegazione dei diversi join, comprese e in particolare le differenze tra FULL OUTER JOIN, RIGHT OUTER JOINe LEFT OUTER JOIN.

Queste due tabelle costituiscono una base per la rappresentazione delle JOINseguenti:

Base

CROSS JOIN

Crossjoin

SELECT *
  FROM citizen
 CROSS JOIN postalcode

Il risultato saranno i prodotti cartesiani di tutte le combinazioni. Nessuna JOINcondizione richiesta:

CrossJoinResult

UNIONE INTERNA

INNER JOIN è uguale al semplice: JOIN

InnerJoin

SELECT *
  FROM citizen    c
  JOIN postalcode p ON c.postal = p.postal

Il risultato saranno combinazioni che soddisfano la JOINcondizione richiesta :

InnerJoinResult

SINISTRA ESTERNO UNISCITI

LEFT OUTER JOIN equivale a LEFT JOIN

LeftJoin

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal

Il risultato sarà tutto, citizenanche se non ci sono partite in postalcode. Ancora una volta JOINè richiesta una condizione:

LeftJoinResult

Dati per giocare

Tutti gli esempi sono stati eseguiti su un Oracle 18c. Sono disponibili su dbfiddle.uk, che è anche il luogo di provenienza degli screenshot dei tavoli.

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;

Confini confusi quando si gioca con JOINeWHERE

CROSS JOIN

CROSS JOINrisultante in righe come L'idea generale / INNER JOIN:

SELECT *
  FROM citizen          c
  CROSS JOIN postalcode p
 WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows

Utilizzare CROSS JOINper ottenere il risultato di un LEFT OUTER JOINrichiede trucchi come l'aggiunta in una NULLriga. È stato omesso.

UNIONE INTERNA

INNER JOINdiventa un prodotto cartesiano. È lo stesso di The General Idea / CROSS JOIN:

SELECT *
  FROM citizen    c
  JOIN postalcode p ON 1 = 1  -- < -- The ON condition makes it a CROSS JOIN

È qui che il join interno può davvero essere visto come il join incrociato con risultati che non corrispondono alla condizione rimossa. Qui nessuna delle righe risultanti viene rimossa.

Usare INNER JOINper ottenere il risultato di un LEFT OUTER JOINrichiede anche dei trucchi. È stato omesso.

SINISTRA ESTERNO UNISCITI

LEFT JOINrisulta nelle righe come L'idea generale / CROSS JOIN:

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN

LEFT JOINrisulta nelle righe come L'idea generale / 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

I problemi con il diagramma di Venn

Una ricerca di immagini su "sql join cross inner external" mostrerà una moltitudine di diagrammi di Venn. Avevo una copia stampata di uno sulla mia scrivania. Ma ci sono problemi con la rappresentazione.

Il diagramma di Venn è eccellente per la teoria degli insiemi, in cui un elemento può trovarsi in uno o entrambi gli insiemi. Ma per i database, un elemento in un "set" mi sembra una riga in una tabella e quindi non è presente in nessuna altra tabella. Non esiste una riga presente in più tabelle. Una riga è unica per la tabella.

I self join sono un caso angolare in cui ogni elemento è in effetti lo stesso in entrambi i set. Ma non è ancora libero da nessuno dei problemi di seguito.

L'insieme Arappresenta l'insieme a sinistra (la citizentabella) e l'insieme Bè l'insieme a destra (la postalcodetabella) nella discussione di seguito.

CROSS JOIN

Ogni elemento di entrambi gli insiemi è abbinato a ogni elemento dell'altro insieme, il che significa che abbiamo bisogno di Aquantità di ogni Belemento e Bquantità di ogni Aelemento per rappresentare correttamente questo prodotto cartesiano. La teoria degli insiemi non è fatta per più elementi identici in un insieme, quindi trovo che i diagrammi di Venn rappresentino correttamente impraticabile / impossibile. Non sembra che si UNIONadatti affatto.

Le righe sono distinte. Sono UNION7 righe in totale. Ma sono incompatibili per un SQLset di risultati comune . E non è affatto così che CROSS JOINfunziona:

CrossJoinUnion1

Cercando di rappresentarlo in questo modo:

CrossJoinUnion2Crossing

..ma ora sembra proprio come una INTERSECTION, che è certamente non è . Inoltre non vi è alcun elemento nel fatto INTERSECTIONche si trova effettivamente in nessuno dei due set distinti. Tuttavia, assomiglia molto ai risultati della ricerca simili a questo:

CrossJoinUnionUnion3

Per riferimento un risultato ricercabile per CROSS JOINs può essere visto su Tutorialgateway . Il INTERSECTION, proprio come questo, è vuoto.

UNIONE INTERNA

Il valore di un elemento dipende dalla JOINcondizione. È possibile rappresentarlo a condizione che ogni riga diventi unica per quella condizione. Il significato id=xè vero solo per una riga. Una volta che una riga nella tabella A( citizen) corrisponde a più righe nella tabella B( postalcode) nella JOINcondizione, il risultato presenta gli stessi problemi del CROSS JOIN: La riga deve essere rappresentata più volte e la teoria degli insiemi non è fatta per questo. Nella condizione di unicità, il diagramma potrebbe funzionare, ma tieni presente che la JOINcondizione determina il posizionamento di un elemento nel diagramma. Osservando solo i valori della JOINcondizione con il resto della riga, giusto per la corsa:

InnerJoinIntersection - Riempito

Questa rappresentazione cade completamente a pezzi quando si usa un INNER JOINcon una ON 1 = 1condizione che lo trasforma in a CROSS JOIN.

Con un self- JOIN, le righe sono in realtà elementi identici in entrambe le tabelle, ma rappresentano le tabelle come entrambe Ae Bnon sono molto adatte. Ad esempio, una JOINcondizione autonoma comune che fa in modo che un elemento Acorrisponda a un elemento diverso in B è ON A.parent = B.child, facendo la corrispondenza da Aa Belementi separati. Dagli esempi che sarebbe SQLsimile a questo:

SELECT *
  FROM citizen c1
  JOIN citizen c2 ON c1.id = c2.leader

SelfJoinResult

Significa che Smith è il leader di Green e Jensen.

ISCRIVITI ESTERNO

Ancora una volta i problemi iniziano quando una riga ha più corrispondenze con le righe nell'altra tabella. Ciò è ulteriormente complicato perché si OUTER JOINpuò pensare che corrisponda all'insieme vuoto. Ma nella teoria degli insiemi l'unione di qualsiasi insieme Ce un insieme vuoto è sempre giusta C. Il set vuoto non aggiunge nulla. La rappresentazione di questo di LEFT OUTER JOINsolito mostra solo tutto Aper illustrare che le righe Asono selezionate indipendentemente dal fatto che ci sia o meno una corrispondenza B. Gli "elementi corrispondenti" presentano tuttavia gli stessi problemi dell'illustrazione sopra. Dipendono dalla condizione. E il set vuoto sembra aver vagato per A:

LeftJoinIntersection - Riempito

Clausola WHERE - ha senso

Trovare tutte le righe da a CROSS JOINcon Smith e il codice postale sulla Luna:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   AND p.area = 'Moon';

Dove - risultato

Ora il diagramma di Venn non viene utilizzato per riflettere il JOIN. È usato solo per la WHEREclausola:

Dove

..e questo ha senso.

Quando INTERSECT e UNION hanno senso

INTERSECT

Come spiegato an INNER JOINnon è proprio un INTERSECT. Tuttavia, INTERSECTè possibile utilizzare s sui risultati di query separate. Qui un diagramma di Venn ha senso, perché gli elementi delle query separate sono in realtà righe che appartengono solo a uno dei risultati o entrambi. Intersect ovviamente restituirà risultati solo se la riga è presente in entrambe le query. Ciò SQLcomporterà la stessa riga di quella sopra WHEREe anche il diagramma di Venn sarà lo stesso:

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';

UNIONE

An OUTER JOINnon è un UNION. Tuttavia, UNIONlavorare nelle stesse condizioni di INTERSECT, risultando in un ritorno di tutti i risultati combinando entrambi i SELECTs:

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';

che equivale a:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   OR p.area = 'Moon';

..e dà il risultato:

Unione - Risultato

Anche qui un diagramma di Venn ha senso:

UNIONE

Quando non si applica

Una nota importante è che funzionano solo quando la struttura dei risultati dei due SELECT è la stessa, consentendo un confronto o unione. I risultati di questi due non consentiranno che:

SELECT *
  FROM citizen
 WHERE name = 'Smith'
SELECT *
  FROM postalcode
 WHERE area = 'Moon';

.. provare a combinare i risultati con UNIONdà a

ORA-01790: expression must have same datatype as corresponding expression

Per ulteriore interesse, leggi Dì NO ai diagrammi di Venn quando spieghi i JOIN e i join sql come diagramma di Venn . Entrambi coprono anche EXCEPT.


1

Ci sono molte buone risposte qui con esempi di algebra relazionale molto accurati . Ecco una risposta molto semplificata che potrebbe essere utile per i programmatori dilettanti o principianti con dilemmi di codifica SQL.

Fondamentalmente, il più delle volte, le query JOINsi riducono a due casi:

Per un SELECTsottoinsieme di dati A:

  • utilizzare INNER JOINquando i dati correlati che Bsi stanno cercando DEVONO esistere per la progettazione del database;
  • utilizzare LEFT JOINquando i dati correlati che Bsi stanno cercando POTREBBE o POTREBBE NON esistere per la progettazione del database.

1

La differenza tra inner joine outer joinè la seguente:

  1. Inner joinè un join che combina tabelle basate su tuple corrispondenti, mentre outer joinè un join che combina tabelle basate su tuple abbinate e non corrispondenti.
  2. Inner joinunisce le righe corrispondenti da due tabelle in cui vengono omesse le righe senza corrispondenza, mentre outer joinunisce le righe da due tabelle e le righe senza corrispondenza si riempiono di valore null.
  3. Inner joinè come un'operazione di intersezione, mentre outer joinè come un'operazione di unione.
  4. Inner joinsono due tipi, mentre outer joinsono tre tipi.
  5. outer joinè più veloce di inner join.

1
Un risultato di join esterno è lo stesso di join interno ma più alcune righe aggiuntive, quindi non ho idea del perché pensi che il join esterno sia più veloce. Inoltre quali sono questi "due tipi" di join interno? Suppongo che ti riferisci a pieno, a sinistra e a destra per l'esterno?
Martin Smith,

1
@ M.achaibou Non apportare modifiche che apportano modifiche non necessarie al formato. I nomi degli operatori non sono codici a meno che non vengano utilizzati nel codice. Si prega di non apportare modifiche al significato del post, pubblicare un commento all'autore. Se non hai il rappresentante, aspetta di farlo. Succede che il poster lo abbia approvato, ma per favore non apportare tali modifiche. PS Il join esterno non è più veloce del join interno.
Philipxy
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.