使用JOIN ON和JOIN ON WHERE的不同行为

时间:2012-06-16 12:31:05

标签: mysql join

我有两张表格,如 here

我正在尝试抓取nameregister变量WHEN register变量不存在值。

使用以下查询显示的内容 here

SELECT t2.name, t1.register, t1.mydate 
FROM time t1
RIGHT JOIN user t2
ON t2.user_id=t1.user_id
WHERE (t1.register = 'absent' OR t1.register is null)

当我使用以下查询时,我会获得INCORRECT结果,如 here所示。

SELECT t2.name, t1.register, t1.mydate 
FROM time t1
RIGHT JOIN user t2
ON t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null)

我的问题是:为什么我在上述情况下会得到不同的结果。我在ON子句本身使用WHERE条件,因此我不需要写WHERE条件。

有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:3)

如果将"t1.register = 'absent' OR t1.register is null"条件放在WHERE子句中,它将在连接后应用,而如果将其放在ON子句中,则会影响连接。

这绝对是正常和期望的行为:)

这里你必须把它放在WHERE子句中:)

答案 1 :(得分:1)

我通常不会使用右连接,而是使用左连接...我知道它们实际上是相同的,只是来自您想要记录的连接中的哪个表。正如Olivier所提到的,WHERE子句是在连接条件之后应用的。我通常会首先询问我想要什么...在您的情况下,我希望所有用户都列出注册时间的无关......所以,我只想把它作为

select
      u.Name,
      t.register,
      t.myDate
   from
      users u
         LEFT JOIN time t
            on u.user_id = t.user_id

我的左表(总是想要)是用户...时间是右侧表,我总是试图保持我的“ON”连接条件表示左/右相关性以便于阅读。

现在,这不是你想要的,但它是我开始的地方......现在,如何应用“缺席”状态。由于上面已经获得了所有用户,并且您只想查看“缺席”的条目,请将其添加到JOIN部分,因为这些是您有兴趣看到的唯一条目。

select
      u.Name,
      t.register,
      t.myDate
   from
      users u
         LEFT JOIN time t
            on u.user_id = t.user_id
          AND t.register = 'absent'

所以,只有“缺席”的记录才会显示各自的注册和mydate值...任何其他记录,你仍然会得到每个人。不需要WHERE子句。

但是,如果您只想要某种类型或状态的用户,您可以添加它以限制您想要查看的“用户”...例如

select
      u.Name,
      t.register,
      t.myDate
   from
      users u
         LEFT JOIN time t
            on u.user_id = t.user_id
          AND t.register = 'absent'
   where
      u.SomeStatus = whatever

答案 2 :(得分:0)

您的问题与查询的执行顺序有关。 正常的顺序是

 From
 JOIN
 WHERE
 SELECT

所以,在第一个例子中

SELECT t2.name, t1.register, t1.mydate 
FROM time t1
RIGHT JOIN user t2
ON t2.user_id=t1.user_id
WHERE (t1.register = 'absent' OR t1.register is null)

首先,两个表将根据条件t2.user_id=t1.user_id连接在一起(使用内连接),然后时间表中的所有不匹配行将添加到临时结果表。最后,WHERE子句(t1.register = 'absent' OR t1.register is null)中的条件将应用于临时表以生成最终结果。

在第二个例子中

SELECT t2.name, t1.register, t1.mydate 
FROM time t1
RIGHT JOIN user t2
ON t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null)

首先,两个表根据条件t2.user_id=t1.user_id AND (t1.register = 'absent' OR t1.register is null)连接在一起(使用内连接)。接下来,将时间中的所有不匹配行添加到结果中。

对于所有这些,两个查询的结果不同。

如果使用 INNER JOIN ,则WHERE或ON子句的条件会产生相同的结果。如果您使用 OUTER JOIN(左/右/交叉),它们只会有所不同。