Oracle
 sql >> Database >  >> RDS >> Oracle

Il join esterno di Oracle non funziona come previsto

Sembra che quello che vuoi davvero sia un join INNER. Lascia cadere i (+) e vedi se torni quello che stai cercando. Inoltre, @GordonLinoff dà un eccellente suggerimento:mettiti comodo con l'uso della sintassi del join ANSI, che è sia più espressiva che più comprensibile del vecchio stile "metti tutte le condizioni nella clausola WHERE e poi prova a risolverlo" .

Ecco come riscriverei questa query utilizzando la sintassi di join standard ANSI:

SELECT *
  FROM PER_ALL_ASSIGNMENTS_F paaf
  INNER JOIN PAY_ALL_PAYROLLS_F payr
    ON payr.PAYROLL_ID = paaf.PAYROLL_ID
  WHERE SYSDATE BETWEEN paaf.EFFECTIVE_START_DATE
                    AND paaf.EFFECTIVE_END_DATE AND
        paaf.ASSIGNMENT_TYPE IN ('E', 'C') AND
        paaf.PRIMARY_FLAG = 'Y' AND
        payr.ATTRIBUTE1 = 'TINT' AND
        paaf.EFFECTIVE_START_DATE BETWEEN NVL(payr.EFFECTIVE_START_DATE, TO_DATE('01/01/1000', 'DD/MM/YYYY')) 
                                      AND NVL(payr.EFFECTIVE_END_DATE, TO_DATE('31/12/4712', 'DD/MM/YYYY'))

Un'altra questione minore. Ho notato che stai usando BETWEEN con valori di data che possono essere potenzialmente problematici. Diciamo, ad esempio, che hai un EFFECTIVE_START_DATE del 01-JAN-2013 e un EFFECTIVE_END_DATE del 30-JUN-2013 su qualche riga in PER_ALL_ASSIGNMENTS_F, e diciamo inoltre che la data e l'ora correnti sono 30-JUN-2013 alle 07:02:04. Dati questi valori di dati, questa riga di PER_ALL_ASSIGNMENTS_F NON essere selezionato, anche se potresti aspettarti che lo sia. Il problema è che quando gli unici campi compilati su un valore DATE sono il giorno, il mese e l'anno, l'ora, i minuti e i secondi di default sono zero, quindi la data di fine è veramente 30-JUN-2013 alle 00:00:00, che è precedente alla data/ora corrente del 30-JUN-2013 alle 07:02:04 AM, e di conseguenza il confronto della data fa sì che la riga venga ignorata. Non so come vengono compilati i campi EFFECTIVE_END_DATE nel tuo database - si spera che siano completamente compilati, ad es. 30-JUN-2013 23:59:59 - ma in caso contrario potresti dover fare un confronto delle date simile

TRUNC(SYSDATE) BETWEEN paaf.EFFECTIVE_START_DATE
                   AND paaf.EFFECTIVE_END_DATE

o

SYSDATE BETWEEN paaf.EFFECTIVE_START_DATE
            AND paaf.EFFECTIVE_END_DATE + INTERVAL '1' DAY - INTERVAL '1' SECOND

(La prima è probabilmente una scelta migliore, poiché la seconda forma precluderà l'uso di qualsiasi indice non basato su funzioni che potrebbe esistere in data (EFFECTIVE_START_DATE, EFFECTIVE_END_DATE).

Condividi e divertiti.