sql >> Database >  >> RDS >> Oracle

Oracle outer join werkt niet zoals verwacht

Het klinkt alsof je echt een INNER join wilt. Laat de (+)'s vallen en kijk of je terugkrijgt wat je zoekt. Bovendien doet @GordonLinoff een uitstekende suggestie - ga vertrouwd raken met het gebruik van de ANSI-joinsyntaxis, die zowel expressiever als begrijpelijker is dan de oude stijl "zet alle voorwaarden in de WHERE-clausule en probeer het vervolgens uit te puzzelen" .

Hier is hoe ik deze query zou herschrijven met behulp van de ANSI-standaard join-syntaxis:

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

Nog een kleine kwestie. Ik merk dat je BETWEEN gebruikt met datumwaarden die mogelijk problematisch kunnen zijn. Laten we bijvoorbeeld zeggen dat u een EFFECTIVE_START_DATE van 01-JAN-2013 en een EFFECTIVE_END_DATE van 30-JUN-2013 hebt op een rij in PER_ALL_ASSIGNMENTS_F, en laten we verder zeggen dat de huidige datum en tijd 30-JUN-2013 zijn om 07:02:04 uur. Gezien deze gegevenswaarden zal deze rij van PER_ALL_ASSIGNMENTS_F NIET worden geselecteerd, hoewel je dat misschien zou verwachten. Het probleem is dat wanneer de enige velden die zijn ingevuld op een DATE-waarde de dag, de maand en het jaar zijn, het uur, de minuten en de seconden standaard op nul staan ​​- dus de einddatum is echt 30-JUN-2013 om 00:00:00, dat is vóór de huidige datum/tijd van 30-JUN-2013 om 07:02:04 AM, en bijgevolg zorgt de datumvergelijking ervoor dat de rij wordt genegeerd. Ik weet niet hoe de EFFECTIVE_END_DATE-velden in uw database worden ingevuld - hopelijk zijn ze volledig ingevuld, b.v. 30-JUN-2013 23:59:59 - maar als dat niet het geval is, moet je misschien je datumvergelijking zoiets maken als

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

of

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

(De eerste is waarschijnlijk een betere keuze, omdat de laatste vorm het gebruik van een niet-functie-gebaseerde index uitsluit die mogelijk bestaat op (EFFECTIVE_START_DATE, EFFECTIVE_END_DATE).

Deel en geniet.



  1. TAN() Voorbeelden in SQL Server

  2. Converteer Oracle CLOB-gegevens naar string in c#

  3. Start en stop lokale mysql-instantie vanuit de toepassing

  4. Voeg tabellen samen in twee databases met behulp van SQLAlchemy