Question

I need to add value condition to the FULL OUTER JOIN.

I.e. I'm triyng to do this:

SELECT *
FROM Table1
FULL OUTER JOIN Table2 ON Table1.Field1 = Table2.Field1 AND Table2.Field2 > 5

But this script doesn't work. Actually it looks like the condition (Table2.Field2 > 5) was never applied at all.

The same issue appears for the RIGHT OUTER JOIN, so I think the reason is that when there is RIGHT or FULL join no value conditions applied to the right table in join.
Why is this happening? Is there a conceptual explanation of such behaviour?

And of course the main question is how to solve this issue.

Is there a way to solve this without using subqueries?

SELECT *
FROM Table1
FULL OUTER JOIN (SELECT * FROM Table2 WHERE Table2.Field2 > 5) AS t2 ON Table1.Field1 = t2.Field1
Was it helpful?

Solution

Pretty convulated but no subqueries

SELECT  Table1.*
        , CASE WHEN Table2.Field2 > 5 THEN Table2.Field1 ELSE NULL END
        , CASE WHEN Table2.Field2 > 5 THEN Table2.Field2 ELSE NULL END        
FROM    Table1
        FULL OUTER JOIN Table2 ON Table1.Field1 = Table2.Field1
WHERE   COALESCE(Table2.Field2, 6) > 5
        OR Table1.Field1 = Table2.Field1

Test script

;WITH Table1 AS (
  SELECT * FROM (VALUES
    (1, 1)
    , (2, 2)
    , (5, 5)
    , (6, 6)
  ) AS Table1 (Field1, Field2)
)
, Table2 AS (
  SELECT * FROM (VALUES
    (1, 1)
    , (3, 3)
    , (4, 4)
    , (5, 5)
    , (7, 7)
  ) AS Table2 (Field1, Field2)
)
SELECT  Table1.*
        , CASE WHEN Table2.Field2 > 5 THEN Table2.Field1 ELSE NULL END
        , CASE WHEN Table2.Field2 > 5 THEN Table2.Field2 ELSE NULL END        
FROM    Table1
        FULL OUTER JOIN Table2 ON Table1.Field1 = Table2.Field1
WHERE   COALESCE(Table2.Field2, 6) > 5
        OR Table1.Field1 = Table2.Field1

Results

 Field1 Field2 Field1 Field2
 1      1      NULL   NULL
 5      5      NULL   NULL
 NULL   NULL   7      7
 6      6      NULL   NULL
 1      1      NULL   NULL
 2      2      NULL   NULL

OTHER TIPS

What you want might be reformulated as:

 SELECT *
   FROM Table1
   LEFT JOIN Table2 ON Table1.Field1 = Table2.Field1 AND Table2.Field2 > 5
  UNION ALL
 SELECT *
   FROM Table1
  RIGHT JOIN Table2 ON Table1.Field1 = Table2.Field1
  WHERE Table2.Field2 > 5
    AND Table1.Field1 IS NULL

but using subquery as suggested by yourself is IMO the best option.

This used to confuse me. Now I get it! The conditions after "on" (in your case:Table1.Field1 = Table2.Field1 AND Table2.Field2 > 5 ) tells the join operator which rows from the two tables are joined. This means when and only when row1 from table1 and row2 from tables satisfy both row1.field1 = row2.field2 and row2.field2 > 5 that row1 and row2 are joined. The rest rows are not joined.

So in full outer join, the result set would then be joined rows, non-joined rows from table1 and non-joined rows from table2. In right join, the result set would be joined rows, non-joined rows from table2. In either case, rows from table 2 with field2 <= 5 will be among the result sets of non-joined rows from table2.

This is why "Table2.Field2 > 5" is working properly in left join but not that "properly" in right or full join, but the value conditions do be doing their jobs right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top