2012-06-16 23 views
1

我有两个表如图所示here不同的行为使用JOIN ON和JOIN ON

我正在尝试取nameregister变量当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) 

当我使用下面的查询,我得到错误的结果如图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条件。

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

+0

的查询相同但看看sqlfiddle:p –

+0

查询看起来与我一样 – iedoc

+0

@iedoc,他们是。我从小提琴更新了它们。 – Ben

回答

3

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

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

在这里,你必须把它的WHERE子句:)

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(左/右/横),它们只会有所不同。

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