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

Oracle outer join fungerer ikke som forventet

Det lyder som om, hvad du virkelig ønsker, er en INNER join. Slip (+)'erne og se, om du får det tilbage, du leder efter. Derudover giver @GordonLinoff et glimrende forslag - bliv fortrolig med at bruge ANSI join-syntaksen, som er både mere udtryksfuld og mere forståelig end den gamle stil "sæt alle betingelserne i WHERE-sætningen og prøv derefter at pusle det ud"-stilen .

Sådan omskriver jeg denne forespørgsel ved hjælp af ANSI-standard joinsyntaks:

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

En anden mindre sag. Jeg bemærker, at du bruger BETWEEN med datoværdier, som potentielt kan være problematiske. Lad os f.eks. sige, at du har en EFFECTIVE_START_DATE 01-JAN-2013 og en EFFECTIVE_END_DATE 30-JUN-2013 på en række i PER_ALL_ASSIGNMENTS_F, og lad os yderligere sige, at den aktuelle dato og klokkeslæt er 30-3 JUN-2013 klokken 07:02:04. I betragtning af disse dataværdier vil denne række fra PER_ALL_ASSIGNMENTS_F IKKE blive udvalgt, selvom du måske forventer det. Problemet er, at når de eneste felter, der er udfyldt på en DATO-værdi, er dagen, måneden og året, så er time, minutter og sekunder som standard nul - dermed er slutdatoen virkelig 30-JUN-2013 kl. 00:00:00, hvilket er forud for den aktuelle dato/tidspunkt 30. JUN-2013 kl. 07:02:04, og derfor medfører datosammenligningen, at rækken ignoreres. Jeg ved ikke, hvordan EFFECTIVE_END_DATE-felterne er udfyldt i din database - forhåbentlig er de fuldstændigt udfyldt, f.eks. 30-JUN-2013 23:59:59 - men hvis ikke, er du måske nødt til at lave din datosammenligning til noget lignende

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

eller

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

(Den førstnævnte er sandsynligvis et bedre valg, da sidstnævnte form vil udelukke brugen af ​​ethvert ikke-funktionsbaseret indeks, som kan eksistere på (EFFECTIVE_START_DATE, EFFECTIVE_END_DATE).

Del og nyd.



  1. Vis kun en kolonne, hvis den ikke er nul

  2. Hvordan bruger jeg SQL Server Compact Edition (CE) fra Java?

  3. Mikro-orm fejl:adgangskodegodkendelse mislykkedes for bruger postgres

  4. UTF-8 / Unicode-tekstkodning med RPostgreSQL