在阅读它之后,这不是显式与隐式SQL连接的副本。 答案可能相关(甚至相同),但问题是不同的。
它们之间有什么不同?每一种都应该有什么不同?
如果我正确地理解了这个理论,那么查询优化器应该能够互换地使用这两种方法。
在阅读它之后,这不是显式与隐式SQL连接的副本。 答案可能相关(甚至相同),但问题是不同的。
它们之间有什么不同?每一种都应该有什么不同?
如果我正确地理解了这个理论,那么查询优化器应该能够互换地使用这两种方法。
当前回答
从字面上看,它们是等价的。
在大多数开源数据库(最著名的例子是MySql和postgresql)中,查询计划是出现在关系数据库管理系统中的访问路径选择(Selinger et al, 1979)中的经典算法的变体。在这种方法中,条件有两种类型
引用单个表的条件(用于筛选) 引用两个表的条件(不管它们出现在哪里,都被视为连接条件)
特别是在MySql中,通过跟踪优化器,您可以看到自己的join ..On条件在解析过程中被等价的where条件替换。类似的事情也发生在postgresql中(虽然没有办法通过日志看到它,你必须阅读源代码描述)。
无论如何,主要的一点是,这两种语法变体之间的差异在解析/查询-重写阶段就消失了,甚至没有达到查询计划和执行阶段。因此,就性能而言,它们是否相同是毫无疑问的,它们在进入执行阶段之前就已经完全相同了。
你可以用explain来验证他们的计划是否相同。例如,在postgres中,计划将包含一个join子句,即使你没有在语法中使用join..on。
Oracle和SQL server不是开源的,但是,据我所知,它们基于等价规则(类似于关系代数中的规则),并且它们在这两种情况下也产生相同的执行计划。
显然,对于外部连接,这两种语法风格是不相等的,对于那些你必须使用join…在语法
其他回答
在SQL中,'WHERE'和'ON'子句是一种条件语句,但它们之间的主要区别是,'WHERE'子句用于选择/更新语句中指定条件,而'ON'子句用于连接,在连接表之前,它验证或检查目标表和源表中的记录是否匹配
例如:“WHERE”
SELECT * FROM employee WHERE employee_id=101
例如:- 'ON'
有两个表employee和employee_details,对应的列为employee_id。
SELECT * FROM employee
INNER JOIN employee_details
ON employee.employee_id = employee_details.employee_id
希望我已经回答了你的问题。 回复以获得任何澄清。
让我们考虑一下这些表格:
A
id | SomeData
B
id | id_A | SomeOtherData
id_A是表a的外键
写这个查询:
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;
将提供如下结果:
/ : part of the result
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////+-------+-------------------------+
|/////////////////////////////|
+-----------------------------+
A中有而B中没有的东西意味着B中有空值。
现在,让我们考虑B.id_A中的一个特定部分,并从前面的结果中突出显示它:
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////|///////| |
|/////////////////////|///////| |
|/////////////////////+---+///| |
|/////////////////////|***|///| |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+
写这个查询:
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
AND B.id_A = SpecificPart;
将提供如下结果:
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
|/////////////////////| | |
|/////////////////////| | |
|/////////////////////+---+ | |
|/////////////////////|***| | |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+
因为这将在内部连接中删除不在B.id_A = SpecificPart中的值
现在,让我们把查询改为这样:
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
WHERE B.id_A = SpecificPart;
结果是:
/ : part of the result
* : part of the result with the specific B.id_A
B
+---------------------------------+
A | |
+---------------------+-------+ |
| | | |
| | | |
| +---+ | |
| |***| | |
| +---+---+-------------------------+
| |
+-----------------------------+
因为整个结果是根据B. id_a = SpecificPart过滤的,删除了B. id_a为NULL的部分,这些部分在A中,但不在B中
在INNER join中,它们是可互换的,优化器会随意重新排列它们。
在OUTER连接上,它们不一定是可互换的,这取决于它们所依赖的连接的哪一侧。
我把它们放在任意一个位置,取决于可读性。
您正在尝试连接数据还是过滤数据?
为了可读性,将这些用例分别隔离到ON和WHERE是最有意义的。
在ON中联接数据 在WHERE中过滤数据
如果where子句中存在JOIN条件和过滤条件,那么读取查询将变得非常困难。
性能方面,你应该看不到区别,尽管不同类型的SQL有时处理查询计划的方式不同,所以值得尝试¯\_()_/¯(注意缓存会影响查询速度)
另外,正如其他人注意到的那样,如果使用外部连接,如果将筛选条件放在ON子句中,则会得到不同的结果,因为它只影响其中一个表。
我在这里写了一篇更深入的文章: https://dataschool.com/learn/difference-between-where-and-on-in-sql
关于你的问题,
只要你的服务器能得到它,内部连接的'on'和'where'都是一样的:
select * from a inner join b on a.c = b.c
and
select * from a inner join b where a.c = b.c
并非所有口译员都知道“where”选项,所以可能应该避免使用。当然,“on”从句更清楚。