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筛选的区别的更多相关文章

  1. 【杂记】mysql 左右连接查询中的NULL的数据筛选问题,查询NULL设置默认值,DATE_FORMAT函数

    MySQL左右连接查询中的NULL的数据筛选问题 xpression 为 Null,则 IsNull 将返回 True:否则 IsNull 将返回 False. 如果 expression 由多个变量 ...

  2. sql连接查询中的分类

    sql连接查询中的分类 1.内连接(结果不保留表中未对应的数据) 1.1等值连接:关联条件的运算符是用等号来连接的. 1.2不等值连接:连接条件是出等号之外的操作符 1.3自然连接:特殊的等值连接,在 ...

  3. MySQL左右连接查询中的NULL的数据筛选问题

    这里使用左连接为例子,对于左连接是将左边表的数据显示,右边表中如果没有对应的数据则使用null填充. game表: game_type表: SELECT g.name,g.type_id,t.type ...

  4. 连接查询中on and和on where的区别

    一.区别 1. and条件是在生成临时表时使用的条件,它不管and中的条件是否为真,都会返回左(或者右)边表中的记录. 2.where条件是在临时表生成好后,再对临时表进行过滤的条件.这时已经没有le ...

  5. 关于连接查询主要是左右连接查询中,where和on的区别

    工作中,今天用到左连接查询,我自己造的数据,需要根据条件进行筛选,但是筛选不符合我的要求,最终发现是左右连接中where和on的区别,在作怪,工作中用的表关联太多,我下面简化要点,仅仅把注意点写个简单 ...

  6. SQL Server查询中对于单列数据','分割的数据进行的拆分操作,集合的每一个行变多行

    1.cross apply cross apply 我们可以把它看作成是inner join 来使用 2.outer apply outer apply我们可以把它看做是left join 来使用 注 ...

  7. SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)

    先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...

  8. sql连接查询(inner join、full join、left join、 right join)

    sql连接查询(inner join.full join.left join. right join) 一.内连接(inner join) 首先我这有两张表 1.顾客信息表customer 2.消费订 ...

  9. SQLServer SQL连接查询深度探险(摘录

    SQL连接查询深度探险[摘录] 测试环境: Windows XP Profession MySQL 5.0.45 Oracle 9i DB2 UDB 9.1 测试的SQL脚本如下:此脚本适合MySQL ...

随机推荐

  1. iOS 注册密码加密 添加了时间戳 遇到的问题...

    今天项目 遇到一个事故,我本想用 一个形容这个事故的adj  算了 既然 叫事故 已经能表达我们处于的一种状态, 是这样的: 有小部分用户反应 app无法注册 总提示密码错误的情况 实际 该步骤 已经 ...

  2. 设置debian的静态IP

    欲设置的信息: IP地址:198.9.146.131 子网掩码:255.255.255.0 网关:198.9.146.254 DNS:198.9.9.1 198.9.9.2 首先编辑/etc/netw ...

  3. 自己动手编写Maven的插件

    Maven的插件机制是完全依赖Maven的生命周期的,因此理解生命周期至关重要.本文参考官方文档后使用archetype创建,手动创建太麻烦. 创建创建项目 选择maven-archetype-moj ...

  4. 向上管理(manage up)的的五条原则

    绝大多数的工程师很可能很少关注代码之外的能力,摸爬滚打了将近10年后,我才领悟到除了技术之外还有一项最重要的修炼,那就是"领导与被领导"学(其中包含了换位思考,但不局限于换位思考) ...

  5. 大数据系列之Flume+HDFS

    本文将介绍Flume(Spooling Directory Source) + HDFS,关于Flume 中几种Source详见文章 http://www.cnblogs.com/cnmenglang ...

  6. Team Foundation Server 基本功能

    Team Foundation Server(以下简称TFS)作为Microsoft发布的一个主要用于团队源代码管理工具,以敏捷开发作为其最大的特点而占领部分市场.该文主要介绍 TFS 在 Visua ...

  7. 从客户端中检测到有潜在危险的 Request.Form或Requst.String的值。

    在ASP中客户端请求服务时会出现"从客户端中检测到有潜在危险的 Request.Form或Requst.QueryString的值.",原因是在web.config配置文件中存在这 ...

  8. JavaScript 再认识(一):Function调用模式对this的影响

    近来,学习了一下<JavaScript精粹>,读到了函数这章,理清了JavaScript中this在不同调用模式下的指向. 1.Function调用模式:Function是JavaScri ...

  9. Alamofire源码解读系列(八)之安全策略(ServerTrustPolicy)

    本篇主要讲解Alamofire中安全验证代码 前言 作为开发人员,理解HTTPS的原理和应用算是一项基本技能.HTTPS目前来说是非常安全的,但仍然有大量的公司还在使用HTTP.其实HTTPS也并不是 ...

  10. iOS开发之UIDevice通知

    UIDevice类提供了一个单例对象,它代表着设备,通过它可以获得一些设备相关的信息,比如电池电量值(batteryLevel).电池状态(batteryState).设备的类型(model,比如iP ...