在左连接之前,对左表进行SQL筛选。

13

我已经阅读了SO上的一些帖子,并理解了where子句和on子句之间的区别。但是,大多数这些示例都是在右表中进行过滤(使用左联接时)。如果我有一个如下所示的查询:

select * from tableA A left join tableB B on A.ID = B.ID and A.ID = 20

返回的值与我预期的不同。我原以为它首先过滤左表并仅提取ID = 20的行,然后再与tableB进行左连接。

当然,从技术上讲,这应该与执行以下操作相同:

select * from tableA A left join table B on A.ID = B.ID where A.ID = 20

但是我认为,在执行联接之前,如果您能够筛选表格,则性能会更好。有人可以启发我关于如何处理此SQL并帮助我彻底理解吗?

3个回答

26

left join 的规则很简单,它保留第一个表中的所有行。列的值取决于 on 子句。如果没有匹配,则相应表格的列为 NULL -- 无论是第一个表还是第二个表。

因此,对于这个查询:

select *
from tableA A left join
     tableB B
     on A.ID = B.ID and A.ID = 20;

无论是否匹配,结果集中都包含 A 表中的所有行。当 id 不等于 20 时,仍然从 A 表中取出行和列。但是,由于条件为 false,因此 B 表中的列为 NULL。这是一个简单的规则,它不取决于条件是在第一张表还是第二张表上。

对于此查询:

select *
from tableA A left join
     tableB B
     on A.ID = B.ID 
where A.ID = 20;

from子句保留了A中的所有行。但是,where子句会生效,并过滤行,使结果集中只有id为20的行。

当使用left join时:

  • 第一个表上的过滤条件放在where子句中。
  • 后续表上的过滤条件放在on子句中。

谢谢您的回复,但是您能详细说明一下“当ID不为20时,列值为NULL”这句话吗?您是指如果tableB的ID不是20,则tableB的所有列都将为空吗?这是否有用例?或者第一个表的过滤器应该总是进入where子句中? - TFK
@TFK . . . 我调整了措辞。 - Gordon Linoff

0

如果你有一个表tablea,你可以像这样使用子查询:from (select x.* from tablea X where x.value=20) TA

然后像之前使用tablea一样引用TA。

很可能查询优化器会为你完成这个操作。

Oracle应该有一种方法来显示查询计划。在SQL语句之前加上"Explain plan"。从两个方面查看计划并观察它的执行情况。


你的逻辑是正确的,但优化器并没有以那种方式重写它;它有一个OUTER JOIN操作符。 - BobC

0
在你的第一个 SQL 语句中,A.ID=20 在技术上没有被连接到任何东西。连接用于将两个单独的表连接在一起,ON 语句通过关联列作为键来连接它们。 WHERE 语句允许通过仅在特定列下找到该值的情况下减少返回行数来过滤数据。

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