2010-03-23 172 views
18

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

当我使用下面的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 s。有没有办法解决这个问题,还是我正在寻找其他的东西?

回答

35

Try:

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

不要忘记考虑@Date的“时间”部分。如果值在午夜和午夜之间可能有所不同,那么必须使用某种形式的between子句。 – 2010-03-23 15:21:03

+0

这个答案完美无缺,谢谢。 菲利普:感谢那个指针,虽然我在这个项目的早些时候遇到了这个问题,但是我最终把它修复到了我的C#代码中,删除了所有的时间部分,每天都会默认到午夜。 – Wesley 2010-03-23 15:30:22

+1

@韦斯利,最好是“落地”日期时间数据类型来消除时间,所以时间是00:00:00.000而不是午夜。 – 2010-03-23 15:32:24

2

添加在LEFT OUTER JOIN声明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 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) 
5

您可以使用此where子句:

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

当与外部工作联接,最好到f actor ON子句中的任何“isnull work”,而不是where子句 – 2010-03-23 15:22:01

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 
0

你想要的是左侧的接合部之前过滤您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的支持子查询。)

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 (+) [email protected] 
+0

'(+)'是一个Oracle加入运算符,并且OP正在使用SQL-Server。此外,不建议使用外连接的语法,因为它更加有限,并且更难以阅读标准的'Left Join'语法。 [Oracle Docs:Joins](https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm) – Wayne 2016-08-22 17:01:44