SQL连接:where子句与on子句
阅读后,这不是 Explicit与Implicit SQL Joins的重复。 答案可能是相关的(甚至是相同的),但问题是不同的。
有什么区别,每个应该有什么区别?
如果我正确理解该理论,则查询优化器应该可以互换使用。
#1楼
我认为这是连接顺序的影响。 在左上连接的情况下,SQL先执行左连接,然后再执行where过滤器。 在较低的情况下,首先找到Orders.ID = 12345,然后再加入。
#2楼
- 内连接无关紧要
外连接事项
一种。
WHERE
子句:加入之后 。 加入后将过滤记录。b。
ON
子句-加入之前 。 记录(来自右表)将在加入之前被过滤。 结果可能为空(由于OUTER连接)。
示例 :考虑下表:
1. documents:| id | name |--------|-------------|| 1 | Document1 || 2 | Document2 || 3 | Document3 || 4 | Document4 || 5 | Document5 |2. downloads:| id | document_id | username ||------|---------------|----------|| 1 | 1 | sandeep || 2 | 1 | simi || 3 | 2 | sandeep || 4 | 2 | reya || 5 | 3 | simi |
a)在WHERE
子句中:
SELECT documents.name, downloads.idFROM documentsLEFT OUTER JOIN downloadsON documents.id = downloads.document_idWHERE username = 'sandeep'For above query the intermediate join table will look like this.| id(from documents) | name | id (from downloads) | document_id | username ||--------------------|--------------|---------------------|-------------|----------|| 1 | Document1 | 1 | 1 | sandeep || 1 | Document1 | 2 | 1 | simi || 2 | Document2 | 3 | 2 | sandeep || 2 | Document2 | 4 | 2 | reya || 3 | Document3 | 5 | 3 | simi || 4 | Document4 | NULL | NULL | NULL || 5 | Document5 | NULL | NULL | NULL |After applying the `WHERE` clause and selecting the listed attributes, the result will be: | name | id ||--------------|----|| Document1 | 1 || Document2 | 3 |
b)在JOIN
子句中
SELECT documents.name, downloads.idFROM documentsLEFT OUTER JOIN downloadsON documents.id = downloads.document_idAND username = 'sandeep'For above query the intermediate join table will look like this.| id(from documents) | name | id (from downloads) | document_id | username ||--------------------|--------------|---------------------|-------------|----------|| 1 | Document1 | 1 | 1 | sandeep || 2 | Document2 | 3 | 2 | sandeep || 3 | Document3 | NULL | NULL | NULL || 4 | Document4 | NULL | NULL | NULL || 5 | Document5 | NULL | NULL | NULL |Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.After Selecting the listed attributes, the result will be: | name | id ||------------|------|| Document1 | 1 || Document2 | 3 | | Document3 | NULL || Document4 | NULL | | Document5 | NULL |
#3楼
在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
希望我回答了你的问题。 还原以进行任何澄清。
#4楼
对于内部联接, WHERE
和ON
可以互换使用。 实际上,可以在相关子查询中使用ON
。 例如:
update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)
(IMHO)完全使人感到困惑,并且很容易忘记将table1
链接到任何内容(因为“ driver”表没有“ on”子句),但这是合法的。
#5楼
本文清楚地说明了区别。 它还说明“在on_joind_condition与WHEREjoind_condition或joind_alias为空”。
WHERE子句将FROM子句的结果与JOIN一起过滤,而ON子句用于在FROM和JOIN表之间生成表结果。
- 如果要产生连接两个表的表结果,则应使用ON子句确定如何联接表。 当然,例如,在INNER JOIN的情况下,这也可以从原始表中过滤行。
- 如果要过滤连接双方的乘积,则应使用WHERE子句。
#6楼
这是我的解决方案。
SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname
您必须具有 GROUP BY
才能使其正常工作。
希望能有所帮助。
#7楼
为了获得更好的性能,表应具有一个特殊的索引列以用于JOINS。
因此,如果您所依据的列不是那些索引列之一,那么我怀疑将其保留在WHERE中会更好。
因此,您可以使用索引列进行JOIN,然后在JOIN之后在无索引列上运行条件。
#8楼
在内部联接上,它们的含义相同。 但是,如果将联接条件放在WHERE vs ON子句中,则在外部联接中将得到不同的结果。 看看这个相关的问题和答案 (由我自己)。
我认为最习惯的做法是始终将连接条件放在ON子句中(除非它是外部连接,并且您实际上确实希望将其放在where子句中),因为这样会使阅读查询的人更清楚联接表的条件是什么,它还有助于防止WHERE子句长数十行。
#9楼
它们不是同一件事。
考虑以下查询:
SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345
和
SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID AND Orders.ID = 12345
第一个将返回订单及其订单号为12345
行(如果有)。 第二个将返回所有订单,但只有订单12345
将具有与其关联的任何行。
使用INNER JOIN
,这些子句实际上是等效的。 但是,仅仅因为它们在功能上相同而产生相同的结果,并不意味着这两种子句具有相同的语义。
#10楼
在INNER JOIN
它们是可互换的,优化器将随意重新排列它们。
在OUTER JOIN
,它们不一定是可互换的,这取决于它们所依赖的OUTER JOIN
的哪一侧。
我根据可读性将它们放在任何一个地方。
#11楼
对于优化器而言,无论是使用ON还是WHERE定义连接子句都不会有所不同。
但是,恕我直言,我认为在执行连接时使用ON子句更加清晰。 这样,您在查询中就有一个特定的部分,该部分指示如何处理联接以及如何与其他WHERE子句混合。
#12楼
我这样做的方式是:
如果要执行
INNER JOIN
则始终将连接条件放在ON
子句中。 因此,请勿在ON子句中添加任何WHERE条件,而应将它们放在WHERE
子句中。如果要进行
LEFT JOIN
,则将任何WHERE条件添加到LEFT JOIN
右侧表的ON
子句中。 这是必须的,因为添加引用联接右侧的WHERE子句会将联接转换为INNER JOIN。当您要查找不在特定表中的记录时,就是一个例外。 您可以通过以下方式将对RIGHT JOIN表中的唯一标识符(永远不会为NULL)的引用添加到WHERE子句中:
WHERE t2.idfield IS NULL
。 因此,唯一应在联接右侧引用表的地方是查找那些不在表中的记录。
#13楼
在左连接方面, where子句与on子句之间有很大的区别。
这是示例:
mysql> desc t1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| fid | int(11) | NO | | NULL | |
| v | varchar(20) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
表t2的ID为fid。
mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| v | varchar(10) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
查询“ on子句”:
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' -> ;
+----+-----+---+------+------+
| id | fid | v | id | v |
+----+-----+---+------+------+
| 1 | 1 | H | NULL | NULL |
| 2 | 1 | B | NULL | NULL |
| 3 | 2 | H | NULL | NULL |
| 4 | 7 | K | NULL | NULL |
| 5 | 5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)
查询“ where子句”:
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id | v |
+----+-----+---+------+------+
| 4 | 7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)
很明显,对于行t1.v ='K',第一个查询从t1返回一条记录,从t2返回其相关行(如果有)。
第二个查询从t1返回行,但仅对于t1.v ='K'将具有任何关联的行。
#14楼
通常,一旦两个表已经连接,就在WHERE子句中处理过滤。 有可能,尽管您可能想要在连接它们之前过滤一个或两个表。 即,where子句适用于整个结果集,而on子句仅适用于有问题的联接。
#15楼
我认为可以通过SQL的逻辑逻辑顺序来最好地解释这种区别,即简化:
FROM
(包括联接)WHERE
GROUP BY
- 集合体
HAVING
WINDOW
SELECT
DISTINCT
UNION
,INTERSECT
,EXCEPT
ORDER BY
OFFSET
FETCH
联接不是select语句的子句,而是FROM
内的运算符。 这样,当逻辑处理到达WHERE
子句时,属于相应JOIN
运算符的所有ON
子句在逻辑上已经“已经发生”。 这意味着,例如在使用LEFT JOIN
的情况下,在应用WHERE
子句时,外部LEFT JOIN
的语义已经发生。
我已经在此博客文章中更深入地解释了以下示例 。 运行此查询时:
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;
LEFT JOIN
实际上没有任何有用的效果,因为即使演员没有在电影中放映,该演员也将被过滤,因为其FILM_ID
将为NULL
,而WHERE
子句将过滤该行。 结果是这样的:
ACTOR_ID FIRST_NAME LAST_NAME COUNT
--------------------------------------
194 MERYL ALLEN 1
198 MARY KEITEL 1
30 SANDRA PECK 1
85 MINNIE ZELLWEGER 1
123 JULIANNE DENCH 1
即就像我们内部连接两个表一样。 如果我们在ON
子句中移动过滤谓词,则它现在成为外部联接的条件:
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_idAND film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;
表示结果将包含没有电影或没有FILM_ID < 10
电影的FILM_ID < 10
ACTOR_ID FIRST_NAME LAST_NAME COUNT
-----------------------------------------
3 ED CHASE 0
4 JENNIFER DAVIS 0
5 JOHNNY LOLLOBRIGIDA 0
6 BETTE NICHOLSON 0
...
1 PENELOPE GUINESS 1
200 THORA TEMPLE 1
2 NICK WAHLBERG 1
198 MARY KEITEL 1
简而言之
从逻辑上讲,请始终将谓词放在最有意义的位置。
#16楼
让我们考虑一下这些表:
一种
id | SomeData
乙
id | id_A | SomeOtherData
id_A
是表A
的外键
编写此查询:
SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;
将提供此结果:
/ : part of the resultB+---------------------------------+A | |
+---------------------+-------+ |
|/|///| |
|/|///| |
|/|///| |
|/|///| |
|/+-------+-------------------------+
|/|
+-----------------------------+
A中有什么但B中没有什么意味着B的值为空。
现在,让我们考虑B.id_A
的特定部分,并从之前的结果中突出显示它:
/ : part of the result
* : part of the result with the specific B.id_AB+---------------------------------+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_AB+---------------------------------+A | |
+---------------------+-------+ |
|/| | |
|/| | |
|/+---+ | |
|/|***| | |
|/+---+---+-------------------------+
|/|
+-----------------------------+
因为这会删除内部B.id_A = SpecificPart
中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_AB+---------------------------------+A | |
+---------------------+-------+ |
| | | |
| | | |
| +---+ | |
| |***| | |
| +---+---+-------------------------+
| |
+-----------------------------+
因为根据B.id_A = SpecificPart
过滤了整个结果, B.id_A = SpecificPart
删除了B中没有的部分B.id_A = NULL
。
#17楼
您是要联接数据还是过滤数据?
为了提高可读性,将这些用例分别隔离在ON和WHERE上是最有意义的。
- 在ON中加入数据
- 在WHERE中过滤数据
读取在WHERE子句中存在JOIN条件和过滤条件的查询可能变得非常困难。
从性能上来说,您应该看不出有什么区别,尽管不同类型的SQL有时对查询计划的处理方式也不同,因此值得尝试¯\\_(ツ)_/¯
(请注意缓存会影响查询速度)
另外,正如其他人指出的那样,如果使用外部联接,则将过滤条件放在ON子句中将得到不同的结果,因为它仅影响其中一个表。
我在这里写了一篇更深入的文章: https : //dataschool.com/learn/difference-between-where-and-on-in-sql
SQL连接:where子句与on子句相关推荐
- ASP.NET网站开发——LINQ TO SQL 查询数据库数据(八大子句)
LINQ查询字句概述 1.查询(Query)是一组指令,这些指令可以从一个或多个给定的数据源中检索数据,并指定检索结果的数据类型和表现形式. 2.查询表达式是一种用查询语法表示的表达式,由一组用类似于 ...
- Sql优化系列之(1)__where子句条件优化
1.为什么要进行SQL优化 系统优化中一个很重要的方面就是SQL语句的优化.对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要 ...
- sql limit 子句_SQL按子句概述和示例
sql limit 子句 This article will cover the SQL ORDER BY clause including syntax, usage scenarios to so ...
- sql limit 子句_SQL有子句–综合指南
sql limit 子句 Hi, folks. In this article, we will be focusing on SQL Having Clause in detail. 嗨伙计. 在本 ...
- SQL语句中,为什么where子句不能使用列别名,而order by却可以?
当我们使用某个表达式作为输出的一列时,我们无法再Where条件中直接使用该列作判断条件. 例如下面的SQL语句: select id, (c1 + c2) as s from t1 where ...
- 当WHERE子句、GROUP BY子句和HAVING子句同时出现在一个查询中时,SQL的执行顺序
当WHERE子句.GROUP BY子句和HAVING子句同时出现在一个查询中时,SQL的执行顺序如下: (1) 执行WHERE子句,从表中选取行. (2) 由GROUP BY 子句对选取的行进行分组. ...
- 5、HIVE DML操作、load数据、update、Delete、Merge、where语句、基于分区的查询、HAVING子句、LIMIT子句、Group By语法、Hive 的Join操作等
目录: 4.2.1 Load文件数据到表中 4.2.2查询的数据插入到表中 4.2.3将Hive查询的结果存到本地Linux的文件系统目录中 4.2.4通过SQL语句的方式插入数据 4.2.5 UPD ...
- SQL连接的理解和使用(内连接:自然连接等值连接,外连接:左连接右连接全外连接)
目录 一.连接的介绍 连接是什么? 连接分几种? 条件连接 等值连接 自然连接 二.连接的使用 内连接 INNER JOIN 内连接与等值连接区别 内连接与自然连接区别 外连接 OUTER JOIN ...
- SQL 连接 JOIN 例解
SQL 连接 JOIN 例解.(左连接,右连接,全连接,内连接,交叉连接,自连接) 最近公司在招人,同事问了几个自认为数据库可以的应聘者关于库连接的问题,回答不尽理想- 现在在这写写关于它们的作用 假 ...
最新文章
- 你现在还在使用刷脸支付吗?不,刷手支付已来!!!不侵犯隐私、秒速支付...
- c++ opencv编程实现暗通道图像去雾算法_OpenCV图像处理专栏十五 |一种基于亮度均衡的图像阈值分割技术...
- 磁盘格式化,磁盘挂载,手动增加swap空间
- LeetCode 21合并两个有序链表22括号生成
- Qtum 量子链跨链原子激活 实现 QTUM-BTC 交换
- 用Spring长轮询Tomcat
- 869. 重新排序得到 2 的幂
- 计算机的双一流学校,分数不够上双一流大学计算机专业,上这些大学也不错,实力非常强...
- 理论基础 —— 查找
- 货币化物联网:实现收益
- acrobat xi pro 简体中文语言支持包_在朋友圈收表情包收到手软?预感下一个好玩的功能会是它...
- Atitit 人工智能目前的进展与未来 包含的技术 v3
- postman测试JSON参数接口
- 关于centos7安装 nginx
- uniapp:索引列表
- Zookeeper2.基于zk的开发入门
- BT源代码学习心得(九):客户端源代码分析(图形界面浅析) -- 转贴自 wolfenstein (NeverSayNever)
- 有关PHP文档生成工具---PHPDocumentor
- IBM ServerGuide 8.50
- miui系统小米手机应用双开默认登陆设置修改方法步骤
热门文章
- pure abstract class(什么是纯抽象类?)
- Android Popwindow 使用
- adb logcat read: unexpected EOF!
- Android 解析 Unable to add window is your activity running?
- Gradle 设置本地maven
- JQuery EasyUi控件值的获取与设置
- jackson 反序列化string_java – 使用Jackson对数组进行反序列化
- iOS架构-制作属于自己的cocoapods以及podspec文件讲解(20)
- python functools.wraps functools.partial实例解析
- 第一讲 网络安全概述笔记