2011-08-24 25 views
6

Ho un problema con una vista che voglio creare. Ho due tabelle unite in un join esterno sinistro, ad esempio tableA e tableB, dove tableB viene lasciato esterno unito.SQL where clausola per outer join sinistro

Voglio selezionare solo quelle righe dalla tabella B dove stato è uguale a 4, quindi aggiungo WHERE state = 4 alla mia query. Ora il set di risultati viene tagliato un po 'perché tutte le righe senza una riga corrispondente in tableB vengono rimosse dal risultato (poiché lo stato non è 4 per quelle righe). Ho anche provato WHERE state = 4 OR state IS NULL, non funziona neanche (dal state tecnicamente non è NULL quando non c'è stato).

Quindi quello che mi serve è una dichiarazione WHERE che viene valutata solo quando effettivamente c'è una riga, esiste una cosa del genere?

Se non vedo due opzioni: join (SELECT * FROM tableB WHERE state = 4) anziché la tabella B, o creare una vista con la stessa istruzione WHERE e partecipare invece. Qual è la migliore opzione per le prestazioni?

Questo è SQL Server 2008 R2 a proposito.

+1

sarebbe interessante cercare di capire il motivo per cui 'WHERE stato = 4 o stato è NULL' non funziona, dal momento che dovrebbe impedire il LEFT jOIN che si trasforma in un interno aderire. –

+0

@Damien_The_Unbeliever - Fornirebbe tutte le righe da TableA non in TableB ma non le righe in cui TableA ha una corrispondenza in TableB dove stato <> 4. http://data.stackexchange.com/stackoverflow/qt/110316/ –

+0

@ Damien_The_Unbeliever: ci sono 3 stati: corrispondente allo stato = 4, corrispondente allo stato <> 4, nessuna corrispondenza – gbn

risposta

6

Le condizioni sono state inserite nella clausola on. Esempio:

select a.this, b.that 
from TableA a 
left join TableB b on b.id = a.id and b.State = 4 
+0

Ah, non lo sapevo! Grazie! – Jasper

4

È possibile aggiungere state = 4 alla condizione di join.

select * 
from T1 
    left outer join T2 
    on T1.T1ID = T2.T1ID and 
     T2.state = 4 
1

Anche più facile di un sottoquery sta espandendo la on clausola, come; appariranno

select * 
from TableA a 
left join 
     TableB b 
on  a.b_id = b.id 
     and b.state = 4 

Tutte le righe da TableA, e solo quelli da TableB con lo stato 4.

SQL Server sarà probabilmente eseguire la visualizzazione, espansa on, e subquery esattamente nello stesso modo. Quindi, per quanto riguarda le prestazioni, dovrebbe esserci poca differenza.

0

approccio alternativo: (1) join interno alla tabella B in cui lo stato è uguale a 4, (2) antijoin alla tabella B per trovare le righe che non esistono, (3) il sindacato dei risultati:

SELECT A1.ID, A1.colA, B1.ColB 
    FROM tableA AS A1 
     INNER JOIN tableB AS B1 
      ON A1.ID = B1.ID 
      AND B1.state = 4 
UNION 
SELECT A1.ID, A1.colA, '{{MISSING}}' AS ColB 
    FROM tableA AS A1 
WHERE NOT EXISTS (
        SELECT * 
        FROM tableB AS B1 
        WHERE A1.ID = B1.ID 
       ); 

alternativa:

SELECT A1.ID, A1.colA, B1.ColB 
    FROM tableA AS A1 
     JOIN tableB AS B1 
      ON A1.ID = B1.ID 
      AND B1.state = 4 
UNION 
SELECT ID, colA, '{{NA}}' AS ColB 
    FROM tableA 
WHERE ID IN (
       SELECT ID 
       FROM tableA 
       EXCEPT 
       SELECT ID 
       FROM tableB 
      );