2010-03-23 19 views
18

Ho due tabelle. indRailType contiene un elenco dei nomi associati a un valore ID che utilizzo in altre tabelle per indicare il tipo di binario. WO_BreakerRail contiene una colonna di data e una colonna di codice ferroviario che corrisponde allo stesso codice in indRailType e alcuni altri dati. C'è una riga in WO_BreakerRail per qualsiasi attività su ciascun tipo di binario, per ogni data. Quindi potrei avere 3 file datate per 3/19/2010, ogni riga indica un codice ferroviario diverso e cosa è successo.LEFT OUTER JOIN con una clausola WHERE

Quando uso il seguente LEFT OUTER JOIN, ottengo una tabella con tutti i tipi di binari, con valori null nelle righe in cui non è successo nulla il 19. Ora, funziona solo perché ho una sola data rappresentata nel mio tavolo WO_BreakerRail in questo momento, il 19. Quando aggiungo più righe con date diverse, le cose andranno in tilt.

Questa è la mia dichiarazione di SQL, che in questo momento mi dà esattamente i risultati che voglio:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail 
    ON indRailType.RailCode = WO_BreakerRail.RailCode 

Ora, quando aggiungo in una clausola WHERE WO_BreakerRail.Date = @Date perdo tutte le righe della JOIN che non è successo niente. Non lo voglio Dalla lettura, sembra un FULL OUTER JOIN è quello che voglio, ma SQL Server Compact Edition non supporta FULL OUTER JOIN s. C'è un modo per aggirare questo, o sto cercando qualcos'altro interamente?

risposta

35

Prova:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType 
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
      AND WO_BreakerRail.Date = @Date 

Così aggiungendo AND WO_BreakerRail.Date = @Date sul unirsi

+1

Non dimenticare di includere la porzione "time" di @Date. Se i valori possono variare tra mezzanotte e mezzanotte, è necessario utilizzare una qualche forma tra una clausola e l'altra. –

+0

Questa risposta ha funzionato perfettamente, grazie. Filippo: Grazie per questo indicatore, anche se mi sono imbattuto in questo problema in precedenza in questo progetto che mi ha sconcertato per un po ', ma ho finito per fissarlo nel mio codice C#, la rimozione di tutte le porzioni di tempo, inadempiente ogni data a mezzanotte. – Wesley

+1

@Wesley, è meglio "floor" tipi di dati datetime per rimuovere il tempo, quindi l'ora è 00: 00: 00.000 e non mezzanotte. –

2

aggiungere il WO_BreakerRail.Date = @Date sulla dichiarazione LEFT OUTER JOIN e non il WHERE:

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode AND WO_BreakerRail.Date = @Date 

o si può aggiungerlo al DOVE:

SELECT 
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
    FROM indRailType 
     LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
    WHERE (WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL) 
5

si potrebbe usare questa clausola where:

WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL 
+3

Quando si lavora con outer join, è meglio f attore qualsiasi "isnull work" nella clausola ON, e non nella clausola where –

15

La condizione predicato deve essere nella clausola On per il join, non nella clausola dove. Il modo in cui Outer si unisce al lavoro, dopo che le condizioni di join sono state analizzate, tutte le righe dal "lato esterno" che non corrispondono al lato interno vengono aggiunte nuovamente .... Ma tutto questo accade prima che la clausola where venga elaborata. Quindi, se il filtro di predicato della clausola where su un attributo dal lato esterno di un join esterno, tutte quelle righe verranno rimosse di nuovo ... (Sono tutte null). Mettere il predicato nella condizione di join, invece, allora si otterrà valutata prima le righe mancanti sono aggiunti nuovamente in ...

SELECT b.ID, t.RailType, b.CreatedPieces, 
     b.OutsideSource, b.Charged, b.Rejected, 
     b.RejectedToCrop 
FROM indRailType t 
    LEFT JOIN WO_BreakerRail b 
     ON t.RailCode = b.RailCode 
      And b.Date = @Date 
0

quello che vuoi è per filtrare la WO_BreakerRail per la data desiderata prima SINISTRA unirlo a indRailType. Se si aggiunge semplicemente l'istruzione WHERE, viene eseguito il contrario, il che risulta nel problema descritto.

Le soluzioni fornite finora dovrebbe funzionare (spostare la condizione nella LEFT JOIN), ma mi piacerebbe suggerire un'alternativa: è possibile utilizzare una sottoquery per specificare l'ordine in cui dovrebbero essere fatte le cose:

SELECT R.ID, indRailType.RailType, R.CreatedPieces, R.OutsideSource, R.Charged, R.Rejected, R.RejectedToCrop 
    FROM indRailType LEFT OUTER JOIN 
     (SELECT * FROM WO_BreakerRail WHERE Date = @Date) R 
     ON indRailType.RailCode = R.RailCode 

(testato, ma per quanto ne so, SQL Server CE supporta subquery.)

1

o si può aggiungerlo alla WHERE:

SELECT WO_BreakerRail.ID, indRailType.RailType, 
    WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType, WO_BreakerRailCode 
WHERE indRailType.RailCode = WO_BreakerRail.RailCode(+) 
AND WO_BreakerRail.Date (+) [email protected] 
+0

Il '(+)' è un Oracle registrazione operatore e l'OP sta usando SQL-Server. Inoltre, che la sintassi per outer join non è raccomandato per l'uso in quanto è più limitato e più difficili da leggere che la sintassi standard 'Sinistra Join'. [Oracle Documenti: entra a far parte] (https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm) – Wayne

Problemi correlati