Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle Outer Join funktioniert nicht wie erwartet

Es hört sich so an, als ob Sie wirklich einen INNER Join wollen. Lassen Sie die (+)'s weg und sehen Sie, ob Sie zurückbekommen, wonach Sie suchen. Darüber hinaus macht @GordonLinoff einen hervorragenden Vorschlag - machen Sie sich mit der Verwendung der ANSI-Join-Syntax vertraut, die sowohl ausdrucksstärker als auch verständlicher ist als der alte Stil "alle Bedingungen in die WHERE-Klausel einfügen und dann versuchen, sie zu lösen". .

So würde ich diese Abfrage mit der Join-Syntax nach ANSI-Standard umschreiben:

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'))

Noch eine Nebensache. Mir ist aufgefallen, dass Sie BETWEEN mit Datumswerten verwenden, was potenziell problematisch sein kann. Angenommen, Sie haben in einer Zeile in PER_ALL_ASSIGNMENTS_F ein EFFECTIVE_START_DATE vom 01.01.2013 und ein EFFECTIVE_END_DATE vom 30.06.2013, und weiter sagen wir, dass das aktuelle Datum und die aktuelle Uhrzeit der 30.06.2013 sind um 07:02:04 Uhr. Angesichts dieser Datenwerte wird diese Zeile von PER_ALL_ASSIGNMENTS_F NICHT ausgewählt werden, obwohl Sie es vielleicht erwarten würden. Das Problem besteht darin, dass, wenn die einzigen Felder, die für einen DATE-Wert ausgefüllt werden, Tag, Monat und Jahr sind, Stunde, Minuten und Sekunden standardmäßig auf Null gesetzt werden – somit ist das Enddatum wirklich 30. Juni 2013 um 00:00:00 Uhr, was vor dem aktuellen Datum/der aktuellen Uhrzeit des 30. Juni 2013 um 07:02:04 Uhr liegt, und folglich führt der Datumsvergleich dazu, dass die Zeile ignoriert wird. Ich weiß nicht, wie die EFFECTIVE_END_DATE-Felder in Ihrer Datenbank ausgefüllt sind - hoffentlich sind sie vollständig ausgefüllt, z. 30-JUN-2013 23:59:59 - aber wenn nicht, müssen Sie Ihren Datumsvergleich vielleicht so ähnlich machen

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

oder

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

(Die erstere ist wahrscheinlich die bessere Wahl, da die letztere Form die Verwendung von nicht funktionsbasierten Indizes ausschließt, die möglicherweise am (EFFECTIVE_START_DATE, EFFECTIVE_END_DATE) existieren.

Teilen und genießen.