views:

279

answers:

1

In general, I believe "FULL OUTER JOIN Considered Harmful", to turn the phrase.

Background:

http://weblogs.sqlteam.com/jeffs/archive/2007/04/19/Full-Outer-Joins.aspx

But I do have a specific situation where it would be really handy:

Given:

CREATE VIEW Calcs(c1, c2, c3, fordate, ...other columns) AS
   /* Complicated set of equations, etc. */

And:

CREATE TABLE Overrides(c1, c2, c3, fordate)

I need to adjust the View above to follow this logic:

  1. For any Calcs rows whose calculated date has no corresponding Override, select the calculated values.
  2. For any Calcs rows whose calculated date matches an Override date, select the override values.
  3. For any Override rows with no corresponding row in Calcs, select the override values.

Now, usually I would just do a three part query:

CREATE VIEW Calcs AS ... (current logic)

CREATE VIEW CalcsWithOverrides AS

   SELECT * FROM Calcs WHERE NOT EXISTS (match in Overrides)

   UNION ALL

   SELECT override.c1, override.c2, override.c3, (other non-overridden columns)
       FROM Calcs INNER JOIN Overrides

   UNION ALL

   SELECT *, (null placeholders for non-overridden columns) FROM Overrides WHERE
       NOT EXISTS (match in Calcs)

And yet, that seems a lot less straightforward than using an OUTER JOIN:

   SELECT
       COALESCE(Calcs.fordate, Overrides.fordate) AS fordate,
       -- Note that I am not using COALESCE() below on purpose: a null override should still override any calculated value
       CASE WHEN Overrides.fordate IS NULL THEN Calcs.c1 ELSE Overrides.c1 END AS C1,
       CASE WHEN Overrides.fordate IS NULL THEN Calcs.c2 ELSE Overrides.c2 END AS C2,
       CASE WHEN Overrides.fordate IS NULL THEN Calcs.c3 ELSE Overrides.c3 END AS C3,
       (....other columns from calcs that will be null for override-only rows...)
   FROM
       Calcs
       FULL OUTER JOIN Overrides ON Overrides.fordate = Calcs.fordate

So, is this a situation where an OUTER JOIN is justified, or is there a better alternative than the one above?

+6  A: 

You want a full join here, so I don't think it's considered harmful at all. That's the best way to get to your solution set. I'd run the query execution play on each way to see which would be fastest, but my guess is that the full join would be.

Just remember that there is a distinct difference between a condition in a where clause and a condition in a join clause when dealing with outer joins. Where limits the whole result set, join limits the rows that get matched.

Eric
That last sentence(so true) brought back bad memories....
dverespey
lol @dverespey--been there done that
richardtallent