完全外联这真是个坏事吗?

时间:2009-07-29 19:23:34

标签: sql-server tsql outer-join

总的来说,我认为“FULL OUTER JOIN被认为是有害的”,以改变这句话。

背景:

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

但我确实有一个特定的情况,它会非常方便

假设:

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

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

我需要调整上面的视图以遵循以下逻辑:

  1. 对于计算出的日期没有相应覆盖的任何 Calcs 行,请选择计算出的值。
  2. 对于计算日期匹配的 Calcs 一个覆盖日期,请选择覆盖值。
  3. 对于 Calcs 中没有对应行的覆盖行,请选择覆盖值。
  4. 现在,通常我只会做三部分查询:

    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)
    

    然而,这似乎比使用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
    

    那么,这是一种情况,其中OUTER JOIN是合理的,还是有一个更好的替代方案?

1 个答案:

答案 0 :(得分:8)

你想在这里完全加入,所以我认为它根本不被认为是有害的。这是获得解决方案集的最佳方式。我会在每个方向上运行查询执行游戏以查看哪个会最快,但我的猜测是完全连接将是。

请记住,在处理外连接时,where子句中的条件与join子句中的条件之间存在明显差异。 Where限制整个结果集,join限制匹配的行。