2011-01-24 10 views
13

Sono curioso di sapere perché è necessario utilizzare LEFT JOIN poiché è possibile utilizzare le virgole per selezionare più tabelle.Unire a sinistra o selezionare da più tabelle utilizzando la virgola (,)

Quali sono le differenze tra LEFT JOIN e utilizzare le virgole per selezionare più tabelle.

Quale è più veloce?

Qui è il mio codice:

SELECT mw.*, 
      nvs.* 
    FROM mst_words mw 
LEFT JOIN (SELECT no as nonvs, 
        owner, 
        owner_no, 
        vocab_no, 
        correct 
      FROM vocab_stats 
      WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0) 
     AND mw.level = 1 

... e:

SELECT * 
    FROM vocab_stats vs, 
     mst_words mw 
WHERE mw.no = vs.vocab_no 
    AND vs.correct > 0 
    AND mw.level = 1 
    AND vs.owner = 1111 
+1

Il primo è un esempio JOIN OUTER (in questo caso, SINISTRA) (ANSI-92), quest'ultimo è un JOIN INTERNO (ANSI-89, che non supporta OUTER join). A meno che non ci sia sempre un record per collegare le due tabelle, è improbabile che restituiscano gli stessi risultati. –

+0

@OMG Quest'ultimo è 'not' INNER JOIN. È più vicino a un CROSS JOIN per definizione poiché è un prodotto cartesiano. – RichardTheKiwi

+1

sintassi ANSI-89 ... il piano di spiegazioni è identico all'utilizzo di '... DALL'ORDINARIO MSTWORD DI VOCAB_STATS w ON.no = v.vocab_no ...'. Di nuovo - ** no, la seconda query non restituisce un prodotto cartesiano **. –

risposta

3

Prima di tutto, per essere completamente equivalente, la prima query avrebbe dovuto essere scritta

SELECT mw.*, 
      nvs.* 
    FROM mst_words mw 
LEFT JOIN (SELECT * 
      FROM vocab_stats 
      WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0) 
     AND mw.level = 1 

In modo che mw * e NVS * insieme producono lo stesso insieme come la seconda query singolare *. La query così come è stata scritta può utilizzare un JOIN INTERNO, poiché include un filtro su nvs.correct.

La forma generale

TABLEA LEFT JOIN TABLEB ON <CONDITION> 

attempts per trovare i record TableB in base alla condizione. Se fallisce, i risultati di TABLEA vengono mantenuti, con tutte le colonne di TableB impostate su NULL. Al contrario

TABLEA INNER JOIN TABLEB ON <CONDITION> 

anche attempts per trovare i record TableB in base alla condizione. Tuttavia, in caso di errore,, il record particolare da TableA viene rimosso dal set di risultati di output.

Lo standard ANSI per CROSS JOIN produce uno Cartesian product tra le due tabelle.

TABLEA CROSS JOIN TABLEB 
    -- # or in older syntax, simply using commas 
TABLEA, TABLEB 

L'intenzione della sintassi è che ogni riga TABLEA è unito a ciascuna riga TabellaB. Quindi 4 righe in A e 3 righe in B producono 12 righe di output. Quando associato a condizioni nella clausola WHERE, a volte produce lo stesso comportamento di INNER JOIN, poiché esprime la stessa cosa (condizione tra A e B => keep o not). Tuttavia, è molto più chiaro quando si legge l'intenzione quando si utilizza INNER JOIN anziché le virgole.

Per quanto riguarda le prestazioni, la maggior parte dei DBMS elaborerà un join SINISTRO più veloce di UN INTERNO INNER. La notazione della virgola può far sì che i sistemi di database interpretino erroneamente l'intenzione e producano un piano di query non valido, quindi un altro vantaggio per la notazione SQL92.

Perché abbiamo bisogno di SINISTRA UNISCI? Se la spiegazione di LEFT JOIN sopra non è ancora sufficiente (mantenere i record in A senza corrispondenze in B), quindi considerare che per ottenere lo stesso, è necessario un complesso UNION tra due set utilizzando la vecchia notazione a virgola per ottenere lo stesso effetto. Tuttavia, come indicato in precedenza, questo non si applica al tuo esempio, che è in realtà un INNER JOIN nascosto dietro un SINISTRO SINISTRA.

Note:

  • La DESTRA join è la stessa di sinistra, tranne che inizia con TableB (lato destro) al posto di A.
  • destra e sinistra ENTRA sono entrambi ESTERNO unisce. La parola OUTER è facoltativa, cioè può essere scritta come LEFT OUTER JOIN.
  • Il terzo tipo di join OUTER è join FULL OUTER, ma non viene discusso qui.
0

Separare il JOIN dal DOVE rende facile da leggere, come la logica non può aderire essere confuso con le condizioni WHERE. Inoltre, sarà generalmente più veloce in quanto il server non avrà bisogno di condurre due query separate e combinare i risultati.

I due esempi che hai fornito non sono realmente equivalenti, dato che hai incluso una sotto-query nel primo esempio. Questo è un esempio migliore:..

SELECT vs.*, mw.* 
FROM vocab_stats vs, mst_words mw 
LEFT JOIN vocab_stats vs ON mw.no = vs.vocab_no 
WHERE vs.correct > 0 
AND mw.level = 1 
AND vs.owner = 1111 
+0

L'SQL non è valido – RichardTheKiwi

+0

Grazie, ho appena rimosso l'errore di battitura. – Bazmatiq

Problemi correlati