sql连接查询中on筛选与where筛选的区别
sql查询这个东西, 要说它简单, 可以很简单, 通常情况下只需使用增删查改配合编程语言的逻辑表达能力,就能实现所有功能。 但是增删查改并不能代表sql语句的所有, 完整的sql功能会另人望而生畏。 就拿比普通增删查改稍微复杂一个层次的连接查询来说, 盲目使用, 也会出现意料之外的危险结果,导致程序出现莫名其妙的BUG。
在连接查询语法中,另人迷惑首当其冲的就要属on筛选和where筛选的区别了, 在我们编写查询的时候, 筛选条件的放置不管是在on后面还是where后面, 查出来的结果总是一样的, 既然如此,那为什么还要多此一举的让sql查询支持两种筛选器呢? 事实上, 这两种筛选器是存在差别的,只是如果不深挖不容易发现而已。
sql中的连接查询分为3种, cross join,inner join,和outer join , 在 cross join和inner join中,筛选条件放在on后面还是where后面是没区别的,极端一点,在编写这两种连接查询的时候,只用on不使用where也没有什么问题。因此,on筛选和where筛选的差别只是针对outer join,也就是平时最常使用的left join和right join。
来看一个示例,有两张数据表,结构和数据如图所示
表main

表ext

可以把这两张表看作是用来存放用户信息的, main放置主要信息,ext表放置附加信息,两张表的关系是1对1的,以id字符作为对应关系键。现在我们需要将地址不为杭州的所有用户信息筛选出来,结果中需要包含main表和ext表的所有字段数据。
select * from main left JOIN exton main.id = ext.id and address <> '杭州'
闭上眼睛, 请用大脑人肉运行一下这段SQL, 想象一下是什么结果。

当把 address <> '杭州' 这个筛选条件放在on之后,查询得到的结果似乎跟我们预料中的不同,从结果中能看出,这个筛选条件好像只过滤掉了ext表中对应的记录,而main表中的记录并没有被过滤掉,也就是上图中标记为红色的那条记录。outer join相对于inner join的一个主要特性就是以一侧的表为基础,但是在这里以左表为基这一点却可以无视筛选条件,这未免也太霸道了一些。
把查询语句稍微改动一下,将地址的筛选条件从on转移至where
select * from main left JOIN ext on main.id = ext.id where address <> '杭州'
结果就如我们预期的那样了

造成这种结果上的差异要从outer join查询的逻辑查询的各个阶段说起。总的来说,outer join 的执行过程分为4步
1、先对两个表执行交叉连接(笛卡尔积)
2、应用on筛选器
3、添加外部行
4、应用where筛选器
就拿上面不使用where筛选器的sql来说,执行的整个详细过程如下
第一步,对两个表执行交叉连接,结果如下,这一步会产生36条记录(此图显示不全)

第二步,应用on筛选器。筛选器中有两个条件,main.id = ext.id and address<> '杭州',符合要求的记录如下

这似乎正是我们期望中查询的结果,然而在接下来的步骤中这个结果会被打乱
第三步,添加外部行。outer join有一个特点就是以一侧的表为基,假如另一侧的表没有符合on筛选条件的记录,则以null替代。在这次的查询中,这一步的作用就是将那条原本应该被过滤掉的记录给添加了回来

是不是不种画蛇添足的感觉, 结果就成了这样

第四步,应用where筛选器
在这条问题sql中,因为没有where筛选器,所以上一步的结果就是最终的结果了。
而对于那条地址筛选在where条件中的sql,这一步便起到了作用,将所有地址不属于杭州的记录筛选了出来

通过上面的讲解,已经能反应出在outer join中的筛选条件在on中和where中的区别,开发人员如能详细了解之中差别,能规避很多在编写sql过程中出现的莫名其妙的错误。
sql连接查询中on筛选与where筛选的区别的更多相关文章
- 【杂记】mysql 左右连接查询中的NULL的数据筛选问题,查询NULL设置默认值,DATE_FORMAT函数
MySQL左右连接查询中的NULL的数据筛选问题 xpression 为 Null,则 IsNull 将返回 True:否则 IsNull 将返回 False. 如果 expression 由多个变量 ...
- sql连接查询中的分类
sql连接查询中的分类 1.内连接(结果不保留表中未对应的数据) 1.1等值连接:关联条件的运算符是用等号来连接的. 1.2不等值连接:连接条件是出等号之外的操作符 1.3自然连接:特殊的等值连接,在 ...
- MySQL左右连接查询中的NULL的数据筛选问题
这里使用左连接为例子,对于左连接是将左边表的数据显示,右边表中如果没有对应的数据则使用null填充. game表: game_type表: SELECT g.name,g.type_id,t.type ...
- 连接查询中on and和on where的区别
一.区别 1. and条件是在生成临时表时使用的条件,它不管and中的条件是否为真,都会返回左(或者右)边表中的记录. 2.where条件是在临时表生成好后,再对临时表进行过滤的条件.这时已经没有le ...
- 关于连接查询主要是左右连接查询中,where和on的区别
工作中,今天用到左连接查询,我自己造的数据,需要根据条件进行筛选,但是筛选不符合我的要求,最终发现是左右连接中where和on的区别,在作怪,工作中用的表关联太多,我下面简化要点,仅仅把注意点写个简单 ...
- SQL Server查询中对于单列数据','分割的数据进行的拆分操作,集合的每一个行变多行
1.cross apply cross apply 我们可以把它看作成是inner join 来使用 2.outer apply outer apply我们可以把它看做是left join 来使用 注 ...
- SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)
先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...
- sql连接查询(inner join、full join、left join、 right join)
sql连接查询(inner join.full join.left join. right join) 一.内连接(inner join) 首先我这有两张表 1.顾客信息表customer 2.消费订 ...
- SQLServer SQL连接查询深度探险(摘录
SQL连接查询深度探险[摘录] 测试环境: Windows XP Profession MySQL 5.0.45 Oracle 9i DB2 UDB 9.1 测试的SQL脚本如下:此脚本适合MySQL ...
随机推荐
- Hadoop伪分布安装配置
安装环境: 系统:Ubuntu 14.10 64bit hadoop:2.5.1 jdk:1.8.0_11 安装步骤: 一.安装JDK 安装 jdk,并且配置环境以及设置成默认 sudo gedi ...
- java基础:数组的复制
- 或许是介绍Android Studio使用Git最详细的文章
欢迎访问我的个人博客转发请注明出处:http://www.wensibo.top/2017/03/12/GitOnAS/ 前言 本文较长,图片很多很多,流量党慎入 使用Git已经有一段时间了,但是之前 ...
- java算法 蓝桥杯(题+答案) 压缩变换
10.压缩变换 (程序设计) 小明最近在研究压缩算法.他知道,压缩的时候如果能够使得数值很小,就能通过熵编码得到较高的压缩比.然而,要使数值很小是一个挑战. 最近,小明需要压缩一些正整数的序列,这些 ...
- 关于IE低版本兼容问题
1,元素浮动之后,能设置宽度的话就给元素加宽度.如果需要宽度是内容撑开,就给它里边的块元素加上浮动: 解决方案:给需要宽度由内容撑开的元素加上浮动 css样式: <style> .box{ ...
- SQL基本编程,分支语句,循环语句,存储过程,触发器
基本编程: 定义变量 declare @变量名 数据类型 赋值 set @变量名 = 值 select @变量名 = 值 取值打印 select @变量名 print @变量名 映射到结果集 打印到消 ...
- NoSQL注入的分析和缓解
本文要点介绍: 1.了解针对NoSQL的新的安全漏洞 2.五类NoSQL攻击手段,比如重言式.联合查询.JavaScript 注入.背负式查询(Piggybacked queries),以及跨域违规 ...
- yii中调整ActiveForm表单样式
Yii2中对于表单和字段的支持组件为ActiveForm和ActiveField, <?php $form = ActiveForm::begin([ 'id' => 'login-for ...
- 【G】系列导航
G.开源的分布式部署解决方案 [G]开源的分布式部署解决方案 - 预告篇 [G]开源的分布式部署解决方案(一) - 开篇 [G]开源的分布式部署解决方案(二) - 好项目是从烂项目基础上重构出来的 [ ...
- iOS开发之数据存储之Preference(偏好设置)
1.概述 很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能. 每个应用都有个NSUserDefaults实例,通过它来存取偏好 ...