将过滤条件放在 join on 语句中是不是等效? [复制]

Posted

技术标签:

【中文标题】将过滤条件放在 join on 语句中是不是等效? [复制]【英文标题】:Is placing the filter condition inside the join on statement equivalent? [duplicate]将过滤条件放在 join on 语句中是否等效? [复制] 【发布时间】:2019-02-12 12:10:08 【问题描述】:

我一直假设以下形式的陈述

SELECT * FROM A LEFT JOIN B ON (A.column1 = B.column2 AND B.column2 = 12321)

总是等价于

SELECT * FROM A LEFT JOIN B ON (A.column1 = B.column2)
WHERE B.column2 = 12321

更笼统地说:

SELECT * FROM A LEFT JOIN B ON (FOREIGN-KEY AND FILTER_ON(B))
WHERE FILTER_ON(A)

应该等价于

SELECT * FROM A LEFT JOIN B ON (FOREIGN-KEY)
WHERE FILTER_ON(A) AND FILTER_ON(B)

情况似乎并非如此...第一种类型提供的结果行数比第二种类型多。

问题:在哪些情况下我的假设是错误的?

【问题讨论】:

学习 SQL 的最佳方式是编程。创建表,插入一些数据,看看是否有区别! (提示:有。将右侧表条件放在 ON 子句中,否则会得到常规的内连接结果。) 最好的理解方式是:在查询中只显示匹配where条件的记录——反之,如果左连接条件不匹配,则显示记录,但是左连接表有一个空行...(如果您使用普通连接(没有左连接),那么这两个语句是等价的,但对于左连接、右连接或全连接不适用。) @jarlh 我不认为这个问题值得 go-and-learn-sql-first 评论。 Mathtec,欢迎加入! 【参考方案1】:

没有。对于外连接,它们是不等价的。

left join所有 行保留在第一个表中,无论 on 子句的计算结果是 true、false 还是 NULL。因此,on 中的条件仅对 first 表无效。

如果您想过滤left join 中的first 表,请将条件放入where。第二张表的条件一般放在on子句中。

【讨论】:

非常感谢您的回复!我已经更新了问题,但我仍然不明白为什么第二个表 B 上的过滤条件对连接条件中的结果有不同的影响。【参考方案2】:

在您的第一个查询中,您编写了LEFT JOIN,这意味着左侧表格中的所有数据。

查询:1 SELECT * FROM A LEFT JOIN B ON (FOREIGN-KEY AND FILTER_ON(A) AND FILTER_ON(B)) 查询:2 SELECT * FROM A LEFT JOIN B ON (FOREIGN-KEY) WHERE FILTER_ON(A) AND FILTER_ON(B) 在 Query:1 中,在LEFT JOIN 中有条件,这意味着当条件变为 false 时,我们仍然有左侧表中的所有数据和 NULL 值和 Table B

如果您在where 子句(Query:2) 中为table B 编写条件,则查询1 和查询2 的结果将出现数据不匹配。因为数据将在查询结果中按条件过滤掉。

【讨论】:

以上是关于将过滤条件放在 join on 语句中是不是等效? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Join语句中的on和where条件过滤的区别

SQL 查询条件放在LEFT OUTER JOIN 的ON语句后与放在WHERE中的区别

SQL语句中 LEFT JOIN 后 ON 和 WHERE 的区别

SQL语句中 LEFT JOIN 后 ON 和 WHERE 的区别

pg中join,left join的使用,将条件放到on和where后面的区别问题

mysql left join中where和on条件的区别