带有WHERE子句的LEFT OUTER JOIN

时间:2010-03-23 15:14:06

标签: sql-server join sql-server-ce

我有两张桌子。 indRailType包含与我在其他表中使用的ID值配对的名称列表,以指示导轨类型。 WO_BreakerRail包含一个日期列和一个铁路代码列,对应indRailType中的相同代码和其他一些数据。对于每个日期,每个铁路类型的任何活动都在WO_BreakerRail中有一行。所以我可以为3/19/2010设置3行,每行代表不同的铁路代码,以及发生了什么。

当我使用以下LEFT OUTER JOIN时,我得到一个包含所有类型轨道的表,在19行中没有发生任何行的行中有空值。现在,这只是起作用,因为我现在只有WO_BreakerRail表中有一个日期,即19日。当我添加更多具有不同日期的行时,事情会变得混乱。

这是我的SQL语句,现在正确地给出了我想要的结果:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail 
    ON indRailType.RailCode = WO_BreakerRail.RailCode

现在,当我添加一个WHERE WO_BreakerRail.Date = @Date子句时,我丢失了JOIN中没有发生任何事情的所有行。我不希望这样。从阅读起,听起来像我想要的OUTER JOIN,但SQL Server Compact Edition不支持FULL OUTER JOIN。有没有办法解决这个问题,还是我完全在寻找其他东西?

6 个答案:

答案 0 :(得分:39)

尝试:

SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, 
    WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged,
    WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode 
            AND WO_BreakerRail.Date = @Date

因此将AND WO_BreakerRail.Date = @Date添加到联接

答案 1 :(得分:15)

谓词条件需要在连接的On子句中,而不是在where子句中。外部连接工作的方式是,在分析连接条件之后,“内侧”与内侧不匹配的所有行都被添加回来......但这一切都发生在处理where子句之前。因此,如果where子句谓词从外连接的外侧过滤属性,则所有这些行将再次被删除...(它们都是空的)。将谓词放在连接条件中,然后在将缺少的行添加回...之前对其进行评估。

SELECT b.ID, t.RailType, b.CreatedPieces, 
       b.OutsideSource, b.Charged, b.Rejected, 
       b.RejectedToCrop 
FROM indRailType t
   LEFT JOIN WO_BreakerRail b
        ON t.RailCode = b.RailCode 
            And b.Date = @Date

答案 2 :(得分:5)

你可以使用这个where子句:

WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL

答案 3 :(得分:2)

WO_BreakerRail.Date = @Date语句中添加LEFT OUTER JOIN,而不是WHERE

SELECT
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
    FROM indRailType 
        LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode AND WO_BreakerRail.Date = @Date

或者您可以将其添加到WHERE:

SELECT
    WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
    FROM indRailType 
        LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode
    WHERE (WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL)

答案 4 :(得分:1)

你想要的是在 LEFT加入WO_BreakerRail之前将你的indRailType过滤到所需的日期。如果你只是添加WHERE语句,则反过来会导致你所描述的问题。

到目前为止提供的解决方案应该有效(将条件移到LEFT JOIN中),但我想建议一个替代方案:您可以使用子查询来指定应该完成的顺序:

SELECT R.ID, indRailType.RailType, R.CreatedPieces, R.OutsideSource, R.Charged, R.Rejected, R.RejectedToCrop
  FROM indRailType LEFT OUTER JOIN
       (SELECT * FROM WO_BreakerRail WHERE Date = @Date) R
       ON indRailType.RailCode = R.RailCode

(未经测试,但据我所知,SQL Server CE支持子查询。)

答案 5 :(得分:1)

或者您可以将其添加到WHERE

SELECT WO_BreakerRail.ID, indRailType.RailType, 
  WO_BreakerRail.CreatedPieces, 
  WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, 
  WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop 
FROM indRailType, WO_BreakerRailCode 
WHERE indRailType.RailCode = WO_BreakerRail.RailCode(+) 
 AND WO_BreakerRail.Date (+) =@Date