sqlsql-serverouter-joinsql-server-2012-localdb

Left outer join in SQL Server 2012 LocalDB not working?


Using SQL Server 2012 (LocalDB), I have three tables:

BESEXT.COMPUTER
BESEXT.ANALYSIS_PROPERTY
BESEXT.ANALYSIS_PROPERTY_RESULT

These contains following info:

First, I perform the following query:

SELECT
    AR.ComputerID,
    AP.Name,
    AR.Value
FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
    AND AP.ID IN (1672, 1673, 1674)
ORDER BY AR.ComputerID, AP.Name

Which yields the following result:

ComputerID  Name                Value
----------  ----                -----
595640      DisplayName         Windows 8.1 x64 - Mobile Device Image - v3.2 
595640      SequenceName        Windows 8.1 x64 - Mobile Device Image
595640      SequenceVersion     3.2
631459      DisplayName         Windows 8.1 x64 - Mobile Device Image - v3.2 
631459      SequenceName        Windows 8.1 x64 - Mobile Device Image
631459      SequenceVersion     3.2

In BESEXT.COMPUTER I have the following values:

ID  ComputerID  ComputerName
--  ----------  ------------
1   595640      PO121203866
2   631459      PO121201739
3   1101805     PO121201100

I want to perform a left outer join of all my computer objects on the first select, so that I know which computers I do not have a value for.

So, first I do a simple inner join on the previous selection:

SELECT
    C.ComputerName,
    R.ComputerID,
    R.Name,
    R.Value
FROM (
    SELECT
        AR.ComputerID,
        AP.Name,
        AR.Value
    FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
    JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
        AND AP.ID IN (1672, 1673, 1674)
) R
JOIN BESEXT.COMPUTER C ON C.ComputerID = R.ComputerID
ORDER BY R.ComputerID, R.Name

Which, predictably, yields the following resultset:

ComputerName    ComputerID  Name            Value
------------    ----------  ----            -----
PO121203866     595640      DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121203866     595640      SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121203866     595640      SequenceVersion 3.2
PO121201739     631459      DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121201739     631459      SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121201739     631459      SequenceVersion 3.2

Now, for the grand finale, let's do the LEFT OUTER JOIN:

SELECT
    C.ComputerName,
    R.ComputerID,
    R.Name,
    R.Value
FROM (
    SELECT
        AR.ComputerID,
        AP.Name,
        AR.Value
    FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
    JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
        AND AP.ID IN (1672, 1673, 1674)
) R
-- LEFT OUTER JOIN ADDED HERE! 
LEFT OUTER JOIN BESEXT.COMPUTER C ON C.ComputerID = R.ComputerID
ORDER BY R.ComputerID, R.Name

This yields the exact same resultset as with the inner join!

This is not what I'm looking for, and it is not at all what I was expecting. Now it's pretty late here and I'm basically doing some work out of insomnia, but I think this is about as simple and example of an Outer Join as it can get, right? The result I'm looking to achieve with the outer join is this:

ComputerName    ComputerID  Name            Value
PO121203866     595640      DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121203866     595640      SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121203866     595640      SequenceVersion 3.2
PO121201739     631459      DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121201739     631459      SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121201739     631459      SequenceVersion 3.2
PO121201100     NULL        NULL            NULL
PO121201100     NULL        NULL            NULL
PO121201100     NULL        NULL            NULL

P.S.: To be completely honest, the result I'm looking for is more like this, but I feel that would be a different question altogether:

ComputerName    Name            Value
------------    ----            -----
PO121203866     DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121203866     SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121203866     SequenceVersion 3.2
PO121201739     DisplayName     Windows 8.1 x64 - Mobile Device Image - v3.2 
PO121201739     SequenceName    Windows 8.1 x64 - Mobile Device Image
PO121201739     SequenceVersion 3.2
PO121201100     DisplayName     NULL
PO121201100     SequenceName    NULL
PO121201100     SequenceVersion NULL

Solution

  • The query you're looking can be written simply as this:

    SELECT ComputerName, A.ComputerID, Name, Value FROM BESEXT.COMPUTER A
    CROSS JOIN (SELECT * FROM BESEXT.ANALYSIS_PROPERTY WHERE ID BETWEEN 1672 AND 1674) B
    LEFT JOIN BESEXT.ANALYSIS_PROPERTY_RESULT C ON A.ComputerId = C.ComputerId AND B.ID = C.PropertyId
    ORDER BY ComputerId, Name
    

    Start by getting all of the computer-property combinations you care about:

    SELECT * FROM BESEXT.COMPUTER A
    CROSS JOIN (SELECT * FROM BESEXT.ANALYSIS_PROPERTY WHERE ID BETWEEN 1672 AND 1674) B
    

    This yields the results:

    ID  ComputerId  ComputerName  ID    Name
    --  ----------  ------------  --    ----
    1   595640      PO121203866   1672  DisplayName
    2   631459      PO121201739   1672  DisplayName
    3   1101805     PO121201100   1672  DisplayName
    1   595640      PO121203866   1673  SequenceName
    2   631459      PO121201739   1673  SequenceName
    3   1101805     PO121201100   1673  SequenceName
    1   595640      PO121203866   1674  SequenceVersion
    2   631459      PO121201739   1674  SequenceVersion
    3   1101805     PO121201100   1674  SequenceVersion
    

    From there, you simply perform a left join on BESEXT.ANALYSIS_PROPERTY_RESULT to get your values, and you include the ORDER BY clause to sort it.