2009-04-16 9 views
5

Ho una tabella, chiamiamola "a" che viene utilizzata in un join di sinistra in una vista che coinvolge un sacco di tabelle. Tuttavia, voglio solo restituire righe di "a" se si uniscono anche a un'altra tabella "b". Quindi il codice esistente sembraRestrizione di un SINISTRO SINISTRA

SELECT .... 
FROM main ... 
... 
LEFT JOIN a ON (main.col2 = a.col2) 

ma è tornando troppe righe, in particolare quelli in cui una non ha una partita in b. Ho provato

SELECT ... 
FROM main ... 
... 
LEFT JOIN (
    SELECT a.col1, a.col2 
    FROM a 
    JOIN b ON (a.col3 = b.col3)) ON (a.col2 = main.col2) 

che mi dà i risultati corretti, ma purtroppo "SPIEGARE piano" dice che facendo in questo modo finisce per costringere un tavolo scansione completa di A e B, che sta facendo cose piuttosto lento. Uno dei miei colleghi ha suggerito un altro LEFT JOIN su b, ma questo non funziona perché mi dà la riga b quando è presente, ma non smette di restituire le righe da una che non ha una corrispondenza in b.

C'è un modo per inserire la condizione main.col2 nel sub-SELECT, che eliminerebbe le scansioni complete della tabella? O qualche altro modo per fare ciò che voglio?

risposta

6
SELECT ... 
FROM .... 
LEFT JOIN (a INNER JOIN b ON ....) ON .... 
+0

Per qualche strana ragione, il join sinistro ora si comporta come un normale join. –

+0

+1 Questo è esattamente quello che stavo per suggerire. –

+0

Ok, non importa cosa ho detto prima - ho risolto quello. –

3
  1. aggiungere un dove (main.col2 = a.col2)

  2. basta fare un join invece di un LEFT JOIN.

+0

Ho bisogno di fare un SINISTRA SINISTRO, perché ho bisogno di restituire le righe in main che non hanno una corrispondenza in a. –

+0

Certo, ma non puoi unirti al join di (main, a) in b come un join non-left? – tpdi

+0

Non c'è una riga di b per ogni riga di main. Fare un join non-sinistro lascerebbe fuori la maggior parte dei main, non è vero? –

0

Cosa succede se si crea una vista che ti consente di unire il join "a" a "b", quindi i tuoi join di sinistra a tale vista?

0
Select ... 
    From Main 
    Left Join a on main.col2 = a.col2 
    where a.col3 in (select b.col3 from b) or a.col3 is null 

potrebbe anche essere necessario fare un po 'indicizzazione sui a.col3 e b.col3

0

prima definire la query tra il tavolo "a" e "b" per assicurarsi che sta tornando le righe desiderate :

Select 
    a.field1, 
    a.field2, 
    b.field3 
from 
    table_a a 

    JOIN table_b b 
     on (b.someid = a.someid) 

poi mettere che come un sub-query della query principale:

select 
    m.field1, 
    m.field2, 
    m.field3, 
    a.field1 as a_field1, 
    b.field1 as b_field1 
from 
    Table_main m 

    LEFT OUTER JOIN 
     (
     Select 
     a.field1, 
     a.field2, 
     b.field3 
     from 
     table_a a 

     JOIN table_b b 
      on (b.someid = a.someid) 
    ) sq 
    on (sq.field1 = m.field1) 

che dovrebbe farlo.

Ah, ho saltato il problema delle prestazioni. Ciò che di solito faccio è mettere la query dalla vista in una stored procedure, così posso generare le sottoquery alle tabelle temporanee e inserirle su indici. Sorprendentemente più veloce di quanto ci si aspetterebbe. :-)

+0

Lo ha già fatto, ma c'è un problema di prestazioni. –

+0

Sembra esattamente come descritto nella domanda. –

+0

Sì, l'ho letto troppo velocemente. :-) –

Problemi correlati