L'ordine di join è importante in SQL?


189

Ignorando le prestazioni, otterrò lo stesso risultato dalla query A e B di seguito? Che ne dici di C e D?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  

11
Cosa <blahblah>? stai unendo A a B e A a C o stai unendo A a B e B a C?
beny23

2
Ciao Beny, il codice nella mia domanda è un'astrazione. Non mi preoccupo di unirmi da A a B o da A a C, voglio solo sapere se la sintassi del genere fornirà risultati identici.
Solo uno studente l'

Risposte:


225

Per i INNERjoin, no, l'ordine non ha importanza. Le query restituiranno gli stessi risultati, a condizione che cambiate le selezioni da SELECT *a SELECT a.*, b.*, c.*.


Per (LEFT , RIGHTo FULL) OUTERjoin, sì, le questioni di ordine - e ( aggiornato cose) sono molto più complicate.

Innanzitutto, i join esterni non sono commutativi, quindi a LEFT JOIN bnon è lo stesso dib LEFT JOIN a

Anche i join esterni non sono associativi, quindi nei tuoi esempi che coinvolgono entrambe le proprietà (commutatività e associatività):

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

è equivalente a :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

ma:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

non è equivalente a :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Un altro esempio (si spera più semplice) di associatività. Pensa a questo come(a LEFT JOIN b) LEFT JOIN c :

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Questo equivale aa LEFT JOIN (b LEFT JOIN c) :

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

solo perché abbiamo ONcondizioni "belle" . Tutti e dueON b.ab_id = a.ab_id e c.bc_id = b.bc_idsono controlli di uguaglianza e non comportano NULLconfronti.

Puoi persino avere condizioni con altri operatori o più complessi come: ON a.x <= b.xoON a.x = 7 oppure ON a.x LIKE b.xoppure ON (a.x, a.y) = (b.x, b.y)e le due query sarebbero comunque equivalenti.

Se tuttavia, una qualsiasi di queste parti coinvolte IS NULLo una funzione correlata a valori null COALESCE(), ad esempio se la condizione fosse b.ab_id IS NULL, le due query non sarebbero equivalenti.


3
È più corretto dire che l'unione esterna è associativa fintanto che nessuno dei predicati può essere soddisfatto da una riga in cui tutte le colonne di una tabella sono NULL, piuttosto che dire che è associativa fintanto che i predicati non implicano IS NULL o "una funzione correlata ai null". Si può facilmente immaginare un predicato che soddisfi la prima descrizione ma non la seconda, come a.somecol > 0 OR b.someothercol > 0; l'associatività potrebbe fallire per quella condizione.
Mark Amery,

Ma sì, penso che sia tecnicamente vero dire che OUTER JOIN è associativo fintanto che il predicato non soddisfa una delle condizioni che descrivo qui: stackoverflow.com/questions/20022196/… (la prima delle quali rompe anche l'associatività per INNER JOINs, ma è un approccio così economico e ovvio per romperlo che forse non vale la pena menzionare.) Vale anche la pena sottolineare che il tipo più comune di JOIN - JOIN su una chiave esterna - non soddisfa nessuna di queste condizioni e quindi è simpatico e associativo.
Mark Amery,

1
@MarkAmery Grazie, stavo facendo fatica a strutturare le mie frasi su quel punto (e ho già votato per la tua risposta;)
ypercubeᵀᴹ

ypercube ho un INNER JOINe un seguitoLEFT JOIN . Funziona in questo modo prima che la query esegua Filteri record sulla base di INNER JOINe quindi si applicherà LEFT JOINai Filteredrecord?
Muhammad Babar,

In effetti, tutti i tipi di join sono associativi, come specificato dallo standard SQL e in base alle definizioni matematiche di associatività, ma non vengono visualizzati associativi perché il riordino delle parentesi richiede lo spostamento della ONclausola (ovvero la "specifica di join") in una nuova posizione . Questa è solo sintassi, però. Se si utilizza la notazione algebrica relazionale (in cui la specifica di join è posizionata sotto l'operatore di join), l'associatività diventa più evidente. Il tuo argomento mostra solo che i join esterni non sono commutativi , il che è corretto
Lukas Eder,

4

per i Join regolari, non è così. TableA join TableBprodurrà lo stesso piano di esecuzione di TableB join TableA(quindi i tuoi esempi C e D sarebbero gli stessi)

per sinistra e destra si unisce. TableA left Join TableBè diverso da TableB left Join TableA, MA è lo stesso diTableB right Join TableA


4
Questo riguarda solo la commutatività, ma gli esempi nella domanda mostrano che l'interlocutore è interessato all'associatività. La risposta di ypercube si rivolge a entrambi.
Mark Amery,

2

Se si tenta di unire C in un campo da B prima di unirsi a B, ovvero:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

la tua richiesta fallirà, quindi in questo caso l'ordine conta.


Sì, è giusto, la risposta corretta dovrebbe essere modificata.
Nir Pengas,

-2

Ottimizzatore Oracle sceglie l'ordine di join delle tabelle per il join interno. Optimizer sceglie l'ordine di join delle tabelle solo in semplici clausole FROM. Puoi controllare la documentazione di Oracle nel loro sito web. E per la sinistra, la destra esterna, la risposta più votata è quella giusta. L'ottimizzatore sceglie l'ordine di join ottimale e l'indice ottimale per ogni tabella. L'ordine di join può influire sull'indice che è la scelta migliore. L'ottimizzatore può scegliere un indice come percorso di accesso per una tabella se è la tabella interna, ma non se è la tabella esterna (e non ci sono ulteriori qualifiche).

L'ottimizzatore sceglie l'ordine di join delle tabelle solo in semplici clausole FROM. La maggior parte dei join che utilizzano la parola chiave JOIN sono suddivisi in join semplici, quindi l'ottimizzatore sceglie il loro ordine di join.

L'ottimizzatore non sceglie l'ordine dei join per i join esterni; utilizza l'ordine specificato nell'istruzione.

Quando si seleziona un ordine di join, l'ottimizzatore tiene conto: La dimensione di ogni tabella Gli indici disponibili su ogni tabella Se un indice su una tabella è utile in un particolare ordine di join Il numero di righe e pagine da scansionare per ogni tabella in ciascuna unire l'ordine

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.