Differenza tra join naturale e join interno


197

Qual è la differenza tra un join naturale e un join interno?


3
Questa domanda non è un duplicato dell'altra, in quanto riguarda i join INNER vs NATURAL, che non sono affrontati nell'altro.

1
Un tempo, questo veniva chiuso come duplicato di Qual è la differenza tra i join sinistro, destro, esterno e interno , ma quella domanda non affronta la differenza tra i join interni e i join naturali.
Jonathan Leffler,

Risposte:


250

Una differenza significativa tra INNER JOIN e NATURAL JOIN è il numero di colonne restituite.

Tener conto di:

TableA                           TableB
+------------+----------+        +--------------------+    
|Column1     | Column2  |        |Column1  |  Column3 |
+-----------------------+        +--------------------+
| 1          |  2       |        | 1       |   3      |
+------------+----------+        +---------+----------+

Il INNER JOINdi TableA e TableB su Column1 torneranno

SELECT * FROM TableA AS a INNER JOIN TableB AS b USING (Column1);
SELECT * FROM TableA AS a INNER JOIN TableB AS b ON a.Column1 = b.Column1;
+------------+-----------+---------------------+    
| a.Column1  | a.Column2 | b.Column1| b.Column3|
+------------------------+---------------------+
| 1          |  2        | 1        |   3      |
+------------+-----------+----------+----------+

La NATURAL JOINtabella A e la tabella B sulla colonna 1 restituiranno:

SELECT * FROM TableA NATURAL JOIN TableB
+------------+----------+----------+    
|Column1     | Column2  | Column3  |
+-----------------------+----------+
| 1          |  2       |   3      |
+------------+----------+----------+

La colonna ripetuta viene evitata.

(AFAICT dalla grammatica standard, non è possibile specificare le colonne di join in un join naturale; il join è rigorosamente basato sul nome. Vedi anche Wikipedia .)

( C'è un imbroglio nel join interno di uscita, il a.e b.le parti non sarebbe nei nomi di colonna, che ci basta column1, column2, column1, column3come le intestazioni. )


2
Ho due tabelle TableA (Column1, Column2) e TableB (Column2, Column3).
2 8

16
La compressione delle colonne nell'output è l'aspetto meno importante di un join naturale. Le cose che devi sapere sono (A) che si unisce automaticamente ai campi con lo stesso nome e (B) riempirà i tuoi *** quando meno te lo aspetti. Nel mio mondo, usare un join naturale è motivo di licenziamento.

8
@JonofAllTrades Puoi spiegare di più su cosa esattamente NATURAL JOINrovinerà, perché è inaspettato e in quale mondo ti trovi?
Bryson

35
Questo è in qualche modo affrontato nella risposta dell'utente 166390. Supponi di avere un naturale legame tra Customerse Employees, unendo EmployeeID. Employeesha anche un ManagerIDcampo. È tutto ok. Quindi, un giorno, qualcuno aggiunge un ManagerIDcampo al Customerstavolo. Il tuo join non si interromperà (sarebbe una misericordia), invece includerà ora un secondo campo e funzionerà in modo errato . Pertanto, un cambiamento apparentemente innocuo può rompere qualcosa solo lontanamente correlato. MOLTO BRUTTO. L'unico lato positivo di un join naturale è salvare un po 'di battitura e il lato negativo è sostanziale.

2
@Jonathan, per quanto riguarda la tua risposta, hai dichiarato che SELECT * FROM TableA INNER JOIN TableB USING (Column1)contiene 4 colonne. Questo non è corretto perché SELECT * FROM TableA INNER JOIN TableB USING (Column1)e SELECT * FROM TableA NATURAL JOIN TableBsono uguali, entrambi danno 3 colonne.
Pacerier,

81
  • Un join interno è quello in cui è richiesta la riga corrispondente nella tabella unita per poter restituire una riga della prima tabella
  • Un join esterno è quello in cui la riga corrispondente nella tabella unita non è richiesta per la restituzione di una riga della prima tabella
  • Un join naturale è un join (è possibile avere uno natural lefto natural right) che presuppone che i criteri di join siano in corrispondenza delle colonne con lo stesso nome in entrambe le tabelle

Eviterei di usare i join naturali come la peste, perché i join naturali sono:

  • non standard sql [SQL 92] e quindi non portatile, non particolarmente leggibile (dalla maggior parte dei programmatori SQL) e forse non supportato da vari strumenti / librerie
  • non informativo; non puoi dire su quali colonne vengono unite senza fare riferimento allo schema
  • le tue condizioni di join sono invisibilmente vulnerabili alle modifiche dello schema: se ci sono più colonne di join naturali e una di queste colonne viene rimossa da una tabella, la query verrà comunque eseguita, ma probabilmente non correttamente e questo cambiamento nel comportamento sarà silenzioso
  • difficilmente vale la pena; stai risparmiando solo circa 10 secondi di digitazione

2
Penso che sia necessario menzionare sinistra / destra per l'esterno (poiché l'esterno è menzionato). Ma per il resto, carino e conciso: manca solo il grazioso diagramma di record SQL.

2
Esistono anche NATURAL LEFT e NATURAL RIGHT. Ma sì, evitali comunque.
MatBailie

1
@Bohemian, Per quanto riguarda "evitarli come la peste", ci sono casi d'uso reali per join naturali per cui sono utili. mariadb.com/kb/en/sql-99/natural-join "... I" Libri NATURAL JOIN Checkouts" dall'aspetto casual sono possibili solo quando le convenzioni di denominazione dei database sono formali e applicate ...."
Pacerier,

2
@sqlvovel c'è molto di sbagliato nel tuo commento, in particolare è errato. Le colonne di join non possono essere "specificate in un elenco selezionato". La definizione di un join naturale è quella di unirsi su * tutte le colonne con nomi simili *. Dal documento MySQL: Il JOIN NATURALE [LEFT] di due tabelle è definito come semanticamente equivalente a un JOIN INNER o un JOIN LEFT con una clausola USING che nomina tutte le colonne presenti in entrambe le tabelle. . E un'altra cosa: in pratica è inutile, perché idè onnipresente e inutile unirsi; sono i soliti nomi di chiavi esterne tablename_id. I join naturali sono una cattiva, cattiva, cattiva idea.
Boemo

2
Non ci sono colonne restituite doppie nella mia query. Uno dei vantaggi della semantica di NJ è che le colonne duplicate non vengono mai restituite. La tua query precedente era anche "meno sicura" della mia perché avrebbe esito negativo se una colonna denominata "a" fosse aggiunta a t2 (poiché la condizione di join senza alias è ambigua). Sospetto che i tuoi pregiudizi contro NJ siano basati sul fatto che non l'hai provato in un prodotto in cui SQL standard è adeguatamente supportato. La domanda qui è su SQL, non su MySQL - cose abbastanza diverse. Non hai ancora corretto la tua risposta in quanto non standard.
nvogel

27

Un join naturale è solo una scorciatoia per evitare di digitare, con la presunzione che il join sia semplice e corrisponda a campi con lo stesso nome.

SELECT
  *
FROM
  table1
NATURAL JOIN
  table2
    -- implicitly uses `room_number` to join

Equivale a...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON table1.room_number = table2.room_number

Quello che non puoi fare con il formato scorciatoia, tuttavia, sono i join più complessi ...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON (table1.room_number = table2.room_number)
    OR (table1.room_number IS NULL AND table2.room_number IS NULL)

2
@JonathanLeffler - In MySQL, certamente.
MatBailie

3
OK - interessante. Ho chiesto perché sembra che lo standard SQL non lo consenta (ma le estensioni sono sempre possibili).
Jonathan Leffler il

Quali DBMS permette questa sintassi non standard: NATURAL JOIN ... USING ()? Lo standard è a NATURAL JOIN boa JOIN b USING (c)
ypercubeᵀᴹ

1
"solo una scorciatoia per evitare di scrivere" è un errore. La sua caratteristica più significativa è che non risulta in colonne duplicate.
giorno

... ad esempio, il risultato della tua query che utilizza un join naturale avrà solo una colonna denominata room_number, mentre i tuoi join interni avranno due colonne denominate room_number.
giorno

13

SQL non è fedele al modello relazionale in molti modi. Il risultato di una query SQL non è una relazione perché può avere colonne con nomi duplicati, colonne "anonime" (senza nome), righe duplicate, valori null, ecc. SQL non considera le tabelle come relazioni perché si basa sull'ordinamento di colonne ecc.

L'idea alla base NATURAL JOINdi SQL è quella di rendere più facile essere più fedeli al modello relazionale. Il risultato delle NATURAL JOINdue tabelle avrà colonne duplicate per nome, quindi nessuna colonna anonima. Allo stesso modo, UNION CORRESPONDINGe EXCEPT CORRESPONDINGvengono forniti per affrontare la dipendenza di SQL dall'ordinamento delle colonne nella UNIONsintassi legacy .

Tuttavia, come per tutte le tecniche di programmazione, è necessario che la disciplina sia utile. Un requisito per il successo NATURAL JOINè rappresentato da colonne con nome coerente, poiché i join sono impliciti su colonne con gli stessi nomi (è un peccato che la sintassi per rinominare le colonne in SQL sia dettagliata, ma l'effetto collaterale è incoraggiare la disciplina quando si nominano le colonne nelle tabelle di base e VIEWS :)

Nota che un SQL NATURAL JOINè un equi-join **, tuttavia questa non è una barra di utilità. Considerare che se NATURAL JOINfosse l'unico tipo di join supportato in SQL sarebbe comunque completo relazionalmente .

Sebbene sia effettivamente vero che chiunque NATURAL JOINpuò essere scritto usando INNER JOINe proiezione (SELECT ), è anche vero che qualsiasi INNER JOINpuò essere scritto usando product ( CROSS JOIN) e restriction ( WHERE); si noti inoltre che una NATURAL JOINtabella tra senza nomi di colonne in comune darà lo stesso risultato di CROSS JOIN. Quindi, se sei interessato solo a risultati che sono relazioni (e perché mai no ?!) allora NATURAL JOINè l'unico tipo di join di cui hai bisogno. Certo, è vero che dal punto di vista del design linguistico le scorciatoie come INNER JOINeCROSS JOIN hanno il loro valore, ma considerano anche che quasi tutte le query SQL possono essere scritte in 10 modi sintatticamente diversi, ma semanticamente equivalenti, e questo è ciò che rende gli ottimizzatori SQL così difficili sviluppare.

Ecco alcune query di esempio (utilizzando il solito database di parti e fornitori ) che sono semanticamente equivalenti:

SELECT *
  FROM S NATURAL JOIN SP;

-- Must disambiguate and 'project away' duplicate SNO attribute
SELECT S.SNO, SNAME, STATUS, CITY, PNO, QTY
  FROM S INNER JOIN SP 
          USING (SNO);                        

-- Alternative projection
SELECT S.*, PNO, QTY
  FROM S INNER JOIN SP 
          ON S.SNO = SP.SNO;

-- Same columns, different order == equivalent?!
SELECT SP.*, S.SNAME, S.STATUS, S.CITY
  FROM S INNER JOIN SP 
      ON S.SNO = SP.SNO;

-- 'Old school'
SELECT S.*, PNO, QTY
  FROM S, SP 
 WHERE S.SNO = SP.SNO;

** L'unione naturale relazionale non è un equijoin, è una proiezione di uno. - philipxy


L'unione naturale relazionale non è un equijoin, è una proiezione di uno. Il join naturale SQL è un equijoin SQL (possibili duplicati) - è definito in termini di utilizzo del join interno.
Philipxy,

@philipxy: grazie, ho apportato delle modifiche. Sentiti libero di modificare - questa o una qualsiasi delle mie risposte - per errori e incomprensioni. Sto ancora imparando da te :)
onedayquando il

9

Un NATURALjoin è solo una breve sintassi per un join specifico INNER - o "equi-join" - e, una volta che la sintassi è stata scartata, entrambi rappresentano la stessa operazione di algebra relazionale. Non è un "tipo diverso" di join, come nel caso di OUTER( LEFT/ RIGHT) o CROSSjoin.

Vedi la sezione equi-join su Wikipedia:

Un join naturale offre un'ulteriore specializzazione di equi-join. Il predicato di join nasce implicitamente confrontando tutte le colonne in entrambe le tabelle che hanno gli stessi nomi di colonna nelle tabelle unite.La tabella unita risultante contiene solo una colonna per ogni coppia di colonne ugualmente denominate.

La maggior parte degli esperti concorda sul fatto che i JOIN NATURALI sono pericolosi e pertanto ne scoraggiano fortemente l'uso. Il pericolo deriva dall'aggiunta involontaria di una nuova colonna, denominata come un'altra colonna ...

Cioè, tutti i NATURALjoin possono essere scritti come INNERjoin (ma il contrario non è vero). Per fare ciò, basta creare il predicato esplicitamente - ad esempio USINGo ON- e, come ha sottolineato Jonathan Leffler, selezionare le colonne del set di risultati desiderato per evitare "duplicati" se lo si desidera.

Buona codifica.


(La NATURALparola chiave può anche essere applicata LEFTe si RIGHTunisce, e lo stesso vale. Un NATURAL LEFT/RIGHTjoin è solo una breve sintassi per un join specifico LEFT/RIGHT .)


2
"NATURAL join è solo una breve sintassi per [snipped]" equi-join "- e, una volta che la sintassi è stata scartata, entrambe rappresentano la stessa algebra relazionale" - hai ragione: è vero per l'algebra relazionale ma la tua risposta non funziona in seguito, ad es. "La maggior parte degli esperti concorda sul fatto che i JOIN NATURALI sono pericolosi e quindi ne scoraggiano fortemente l'uso" - che dicono gli esperti dell'algebra relazionale ?!
onedaywhen

2

Unione naturale: è la combinazione o il risultato combinato di tutte le colonne nelle due tabelle. Restituirà tutte le righe della prima tabella rispetto alla seconda tabella.

Join interno: questo join funzionerà a meno che il nome della colonna non sia sxame in due tabelle


3
Non credo che la tua risposta sia abbastanza chiara e richiederebbe una grande riscrittura per risolverlo.
Onedayquando

0

Un join naturale è il punto in cui 2 tabelle vengono unite sulla base di tutte le colonne comuni.

colonna comune: è una colonna che ha lo stesso nome in entrambe le tabelle + ha tipi di dati compatibili in entrambe le tabelle. Puoi usare solo = operatore

Un Join interno è il punto in cui 2 tabelle vengono unite sulla base di colonne comuni menzionate nella clausola ON.

colonna comune: è una colonna che ha tipi di dati compatibili in entrambe le tabelle ma non deve avere lo stesso nome. È possibile utilizzare solo qualsiasi operatore confronto come =, <=, >=, <, >,<>


-2

la differenza è che int il join interno (equi / default) e il join naturale che nella vincita della colonna comune join natuarl verranno visualizzati in una sola volta ma l'unione interna / equi / default / semplice la colonna comune verrà visualizzata doppia volta.


-2

Il join interno e il join naturale sono quasi uguali, ma c'è una leggera differenza tra loro. La differenza è nell'unione naturale non è necessario specificare la condizione, ma nella condizione di unione interna è obbligatoria. Se specifichiamo la condizione nell'unione interna, le tabelle risultanti sono come un prodotto cartesiano.


Perché non è necessario specificare le condizioni di partecipazione? In quali circostanze la specificazione delle condizioni in un join interno si tradurrebbe in qualcosa di simile a un prodotto cartesiano?
giorno

Chiamare l'unione esterna e interna "quasi la stessa" è un impressione leggermente euforico .. forse puoi approfondire la tua valutazione?
TMOTTM

-3
mysql> SELECT  * FROM tb1 ;
+----+------+
| id | num  |
+----+------+
|  6 |   60 |
|  7 |   70 |
|  8 |   80 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

mysql> SELECT  * FROM tb2 ;
+----+------+
| id | num  |
+----+------+
|  4 |   40 |
|  5 |   50 |
|  9 |   90 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

ISCRIVITI ALL'INTERNO:

mysql> SELECT  * FROM tb1 JOIN tb2 ; 
+----+------+----+------+
| id | num  | id | num  |
+----+------+----+------+
|  6 |   60 |  4 |   40 |
|  7 |   70 |  4 |   40 |
|  8 |   80 |  4 |   40 |
|  1 |    1 |  4 |   40 |
|  2 |    2 |  4 |   40 |
|  3 |    3 |  4 |   40 |
|  6 |   60 |  5 |   50 |
|  7 |   70 |  5 |   50 |
|  8 |   80 |  5 |   50 |
.......more......
return 36 rows in set (0.01 sec) 
AND NATURAL JOIN :

    mysql> SELECT  * FROM tb1 NATURAL JOIN tb2 ;
    +----+------+
    | id | num  |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    |  3 |    3 |
    +----+------+
    3 rows in set (0.01 sec)

-4

Join interno, unisci due tabelle in cui il nome della colonna è lo stesso.

Unione naturale, unisce due tabelle in cui il nome della colonna e i tipi di dati sono uguali.


Questo è completamente errato. A NATURAL JOIN(come diverse persone hanno sottolineato anni fa) è uno in cui i nomi delle colonne sono gli stessi. Il tipo di dati non deve necessariamente essere lo stesso. I campi utilizzati per INNER JOINun'esigenza non hanno lo stesso nome.
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.