SQL中AND和WHERE子句的用法区别是什么?

5

我正在处理一个与Oracle连接的PHP页面。我遇到了以下SQL语句,但不确定它是否能实现预期目标,所以想在这里请教一下。被问及的SQL语句是:

select tableA.id, tableA.name, tableB.details 
from tableA
left join tableB on
tableB.id = tableA.id
and 
tableB.logId = '<logged_in_user>'

现在,当我以一个没有在tableB表中的条目的用户身份登录时,这个查询运行时仍然会返回记录。我的假设是,这个子句应该是'where'而不是'and'

left join tableB on
    tableB.id = tableA.id
    where
    tableB.logId = '<logged_in_user>'

我有两个问题。

  1. 我的理解是正确的吗?
  2. 如果是正确的,那么这个查询为什么会返回结果?'and'子句在检查什么?

请问有人能够解释一下上述查询中使用AND和WHERE之间的区别吗?

谢谢!


由于您没有告诉我们tableA和tableB是什么,或者您希望从此查询中看到什么行为,因此我们无法为您建议查询应该是什么。我们所能做的就是指出left join tableB on ... where tableB.logId = ...总是错误的。 - user359040
3个回答

14

我是对的吗?

不,这个查询:

select tableA.id, tableA.name, tableB.details 
from tableA
left join tableB
on tableB.id = tableA.id
and tableB.logId = '<logged_in_user>'

非常不同于:

select tableA.id, tableA.name, tableB.details 
from tableA
left join tableB
on tableB.id = tableA.id
where tableB.logId = '<logged_in_user>'

这是加入的标准。

第一种情况下,你从A中取出数据,然后当id匹配且有logId时与B连接,否则保留细节为空。

在第二种情况下,你从A中取出数据,然后当id匹配时与B连接,否则保留细节为空,并且你仅保留来自具有logId的B匹配的A行 -- 在此过程中消除了A中的行,并实际上将其转换为内连接。


+1 是一种替代方法,但是使用 INNER JOIN 更加简洁明了,不是吗? - Mike Perrenoud
是的,我无意中在编辑我的最后一段话时添加了那个备注。 :) - Denis de Bernardy
非常感谢!这解释了很多问题。唯一让我还有点困惑的是:在第一个例子中,由于logId找不到与已登录用户匹配的结果,它不应该返回任何结果吗?因为条件and tableB.logId = '<logged_in_user>'没有结果? - Undefined Variable
@open_sourse:左连接B意味着:如果B存在,则从A和B中获取内容,否则从A和null中获取内容。A内连接B意味着:仅当A和B都存在时,才从A和B中获取内容。 - Denis de Bernardy
1
@alex:出于性能原因而选择一个而不是另一个是无关紧要的,因为这两个查询在语义上是不同的:第一个是左连接,第二个是内连接。从性能角度来看,左连接通常会更慢,但基本上是因为它产生了更多的行。 - Denis de Bernardy
显示剩余2条评论

2
现在,当我以一个在tableB表中没有记录的用户身份登录时,该查询仍会返回记录。只需将查询更改为使用内连接,像这样:inner join
select tableA.id, tableA.name, tableB.details 
from tableA
inner join tableB ...

以下是来自Oracle的left join的定义:

LEFT JOIN(也称为LEFT OUTER JOIN)关键字返回左表(table_name1)中的所有行,即使右表(table_name2)中没有匹配项。

inner join的定义如下:

INNER JOIN关键字在两个表中至少有一项匹配时返回行。


谢谢!我意识到内连接是这里的正确方法...我只是还在努力理解为什么AND子句给了我结果 - 我想我需要更多地阅读关于连接的内容。 - Undefined Variable
@open_sourse,因为您需要利用IS NOT NULL来处理NULL值-所以您必须将其添加到您的WHERE子句中。 - Mike Perrenoud

2
如果你只想要两个表中都有值的结果,那么你真正需要的是一个内连接。一旦你完成了这个步骤,过滤结果的位置就不太重要了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接