La vecchia sintassi, con un semplice elenco delle tabelle e l'utilizzo della WHERE
clausola per specificare i criteri di join, è stata deprecata nella maggior parte dei database moderni.
Non è solo per lo spettacolo, la vecchia sintassi ha la possibilità di essere ambigua quando si utilizzano i join INNER e OUTER nella stessa query.
Lasciate che vi faccia un esempio.
Supponiamo che tu abbia 3 tabelle nel tuo sistema:
Company
Department
Employee
Ogni tabella contiene numerose righe, collegate tra loro. Hai più società e ogni azienda può avere più dipartimenti e ogni reparto può avere più dipendenti.
Ok, quindi ora vuoi fare quanto segue:
Elencare tutte le società e includere tutti i loro dipartimenti e tutti i loro dipendenti. Nota che alcune aziende non hanno ancora dipartimenti, ma assicurati di includerli anche tu. Assicurati di recuperare solo i reparti con dipendenti, ma elenca sempre tutte le aziende.
Quindi fai questo:
SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
AND Department.ID = Employee.DepartmentID
Si noti che l'ultimo è un join interno, al fine di soddisfare i criteri che si desidera solo dipartimenti con le persone.
Ok, quindi cosa succede adesso. Bene, il problema è che dipende dal motore del database, da Query Optimizer, dagli indici e dalle statistiche delle tabelle. Lasciatemi spiegare.
Se Query Optimizer determina che il modo per farlo è innanzitutto prendere un'azienda, quindi trovare i reparti e quindi unire i dipendenti con i dipendenti interni, non si otterranno aziende che non dispongono di dipartimenti.
La ragione di ciò è che la WHERE
clausola determina quali righe finiscono nel risultato finale, non singole parti delle righe.
E in questo caso, a causa del join sinistro, la colonna Department.ID sarà NULL, quindi quando si tratta di INNER JOIN to Employee, non c'è modo di soddisfare quel vincolo per la riga Employee, e quindi non lo farà apparire.
D'altra parte, se l'ottimizzatore delle query decide di affrontare prima l'adesione al reparto dipendente e quindi eseguire un'unione a sinistra con le aziende, le vedrai.
Quindi la vecchia sintassi è ambigua. Non c'è modo di specificare ciò che si desidera, senza occuparsi di suggerimenti per le query, e alcuni database non hanno alcun modo.
Inserisci la nuova sintassi, con questa puoi scegliere.
Ad esempio, se vuoi tutte le aziende, come indicato nella descrizione del problema, questo è ciò che scriveresti:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID
Qui si specifica che si desidera che l'unione reparto-dipendente venga eseguita come un'unica unione, quindi si lasciano unire i risultati con le società.
Supponiamo inoltre che desideri solo reparti che contengano la lettera X nel loro nome. Ancora una volta, con i join di vecchio stile, rischi di perdere anche l'azienda, se non ha dipartimenti con una X nel suo nome, ma con la nuova sintassi, puoi farlo:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'
Questa clausola aggiuntiva viene utilizzata per l'unione, ma non è un filtro per l'intera riga. Pertanto, la riga potrebbe essere visualizzata con le informazioni sull'azienda, ma potrebbe contenere NULL in tutte le colonne del reparto e dei dipendenti per quella riga, perché non esiste un reparto con una X nel suo nome per quella società. Questo è difficile con la vecchia sintassi.
Questo è il motivo per cui, tra gli altri fornitori, Microsoft ha deprecato la vecchia sintassi del join esterno, ma non la vecchia sintassi del join interno, a partire da SQL Server 2005 e versioni successive. L'unico modo per comunicare con un database in esecuzione su Microsoft SQL Server 2005 o 2008, utilizzando la sintassi del join esterno di vecchio stile, è impostare quel database in modalità di compatibilità 8.0 (ovvero SQL Server 2000).
Inoltre, alla vecchia maniera, lanciando un sacco di tabelle in Query Optimizer, con un mucchio di clausole WHERE, era simile a dire "eccoti, fai il meglio che puoi". Con la nuova sintassi, Query Optimizer ha meno lavoro da fare per capire quali parti vanno insieme.
Così il gioco è fatto.
LEFT and INNER JOIN è l'onda del futuro.