Search code examples
sqloracle-databasems-accessleft-joinjet

Translating Oracle SQL to Access Jet SQL, Left Join


There must be something I'm missing here. I have this nice, pretty Oracle SQL statement in Toad that gives me back a list of all active personnel with the IDs that I want:

SELECT PERSONNEL.PERSON_ID,
       PERSONNEL.NAME_LAST_KEY,
       PERSONNEL.NAME_FIRST_KEY,
       PA_EID.ALIAS EID,
       PA_IDTWO.ALIAS IDTWO,
       PA_LIC.ALIAS LICENSENO
  FROM PERSONNEL
       LEFT JOIN PERSONNEL_ALIAS PA_EID
          ON     PERSONNEL.PERSON_ID = PA_EID.PERSON_ID
             AND PA_EID.PERSONNEL_ALIAS_TYPE_CD = 1086
             AND PA_EID.ALIAS_POOL_CD = 3796547
             AND PERSONNEL.ACTIVE_IND = 1
       LEFT JOIN PERSONNEL_ALIAS PA_IDTWO
          ON     PERSONNEL.PERSON_ID = PA_IDTWO.PERSON_ID
             AND PA_IDTWO.PERSONNEL_ALIAS_TYPE_CD = 3839085
             AND PA_IDTWO.ACTIVE_IND = 1
       LEFT JOIN PERSONNEL_ALIAS PA_LIC
          ON     PERSONNEL.PERSON_ID = PA_LIC.PERSON_ID
             AND PA_LIC.PERSONNEL_ALIAS_TYPE_CD = 1087
             AND PA_LIC.ALIAS_POOL_CD = 683988
             AND PA_LIC.ACTIVE_IND = 1
 WHERE PERSONNEL.ACTIVE_IND = 1 AND PERSONNEL.PHYSICIAN_IND = 1;

This works very nicely. Where I run into problems is when I put it into Access. I know, I know, Access Sucks. Sometimes one needs to use it, especially if one has multiple database types that they just want to store a few queries in, and especially if one's boss only knows Access. Anyway, I was having trouble with the ANDs inside the FROM, so I moved those to the WHERE, but for some odd reason, Access isn't doing the LEFT JOINs, returning only those personnel with EID, IDTWO, and LICENSENO's. Not everybody has all three of these.

Best shot in Access so far is:

SELECT PERSONNEL.PERSON_ID, 
            PERSONNEL.NAME_LAST_KEY, 
            PERSONNEL.NAME_FIRST_KEY, 
            PA_EID.ALIAS AS EID, 
            PA_IDTWO.ALIAS AS ID2, 
            PA_LIC.ALIAS AS LICENSENO

FROM ((PERSONNEL 
        LEFT JOIN PERSONNEL_ALIAS AS PA_EID ON PERSONNEL.PERSON_ID=PA_EID.PERSON_ID) 
        LEFT JOIN PERSONNEL_ALIAS AS PA_IDTWO ON PERSONNEL.PERSON_ID=PA_IDTWO.PERSON_ID) 
        LEFT JOIN PERSONNEL_ALIAS AS PA_LIC ON PERSONNEL.PERSON_ID=PA_LIC.PERSON_ID

WHERE (((PERSONNEL.ACTIVE_IND)=1) 
        AND ((PERSONNEL.PHYSICIAN_IND)=1) 
        AND ((PA_EID.PRSNL_ALIAS_TYPE_CD)=1086) 
        AND ((PA_EID.ALIAS_POOL_CD)=3796547) 
        AND ((PA_IDTWO.PRSNL_ALIAS_TYPE_CD)=3839085) 
        AND ((PA_IDTWO.ACTIVE_IND)=1) 
        AND ((PA_LIC.PRSNL_ALIAS_TYPE_CD)=1087) 
        AND ((PA_LIC.ALIAS_POOL_CD)=683988) 
        AND ((PA_LIC.ACTIVE_IND)=1));

I think that part of the problem could be that I'm using the same alias (lookup) table for all three joins. Maybe there's a more efficient way of doing this? Still new to SQL land, so any tips as far as that goes would be great. I feel like these should be equivalent, but the Toad query gives me back many many tens of thousands of imperfect rows, and Access gives me fewer than 500. I need to find everybody so that nobody is left out. It's almost as if the LEFT JOINs aren't working at all in Access.


Solution

  • To understand what you are doing, let's look at simplified version of your query:

    SELECT PERSONNEL.PERSON_ID,    
           PA_EID.ALIAS AS EID          
    FROM PERSONNEL         
    LEFT JOIN PERSONNEL_ALIAS AS PA_EID ON PERSONNEL.PERSON_ID=PA_EID.PERSON_ID         
    WHERE PERSONNEL.ACTIVE_IND=1       
            AND PERSONNEL.PHYSICIAN_IND=1      
            AND PA_EID.PRSNL_ALIAS_TYPE_CD=1086
            AND PA_EID.ALIAS_POOL_CD=3796547     
    

    If the LEFT JOIN finds match, your row might look like this:

    Person_ID    EID
    12345        JDB
    

    If it doesn't find a match, (disregard the WHERE clause for a second), it could look like:

    Person_ID    EID
    12345        NULL
    

    When you add the WHERE clauses above, you are telling it to only find records in the PERSONNEL_ALIAS table that meet the condition, but if no records are found, then the values are considered NULL, so they will never satisfy the WHERE condition and no records will come back...

    As Joe Stefanelli said in his comment, adding a WHERE clause to a LEFT JOIN'ed table make it act as an INNER JOIN instead...