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. php写购物车(思路&源码)

    本文介绍一个php实现的购物车代码,功能实现完整,具有一定的参考价值 这里我们为你提供个简单的php购物车代码,从增加购物产品与发生购买了,在商城开发中,这个功能是少不了的 具体分析如下: 对购物车里 ...

  2. Java的JDBC原生态学习以及连接池的用法

    JDBC是什么 JDBC(Java Data Base Connectivity)是Java访问数据库的桥梁,但它只是接口规范,具体实现是各数据库厂商提供的驱动程序(Driver). 应用程序.JDB ...

  3. 【js】基本类型和引用类型的区别

    1.保存方式:(一脸懵逼???) 基本类型是按值访问的,可以在变量的生命周期改变它,但是它是储存在哪里的呢?在浏览器缓存吗?[执行环境中定义的所有变量和函数都存储在执行环境的变量对象里,变量对象我们编 ...

  4. Java面试03|并发及锁

    1.synchronized与Lock的区别 使用synchronized这个关键字实现的同步块有一些缺点: (1)锁只有一种类型 (2)线程得到锁或者阻塞 (3)Lock是在Java语言层面基于CA ...

  5. 3997: [TJOI2015]组合数学

    3997: [TJOI2015]组合数学 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 247  Solved: 174[Submit][Status ...

  6. UI-- Empty Application 新建空工程

    1> Empty Application  在Xcode 5 中的文件路径 : Xode 5 路径:Contents   Developer  Platforms iPhoneOS.platfo ...

  7. java爬虫查找四川大学所有学院的网站的网址中的通知和新闻——以计算机学院为例

    需求:查找四川大学所有学院的网站的网址中的通知和新闻——以计算机学院为例 流程图 3. 具体步骤 (1) 学院的主页为:http://cs.scu.edu.cn/ 获取该页面的所有内容(本文只获取新闻 ...

  8. Android Crash 全局捕获

    Android Crash 全局捕获 首先应该明白的一点是,Android在崩溃后会重新启动崩溃时的那个Activity,如果你的Activity在初始化的时候就直接崩溃,那么你将连续得到 Crash ...

  9. 谈谈java中的volatile

    内存可见性 留意复合类操作 解决num++操作的原子性问题 禁止指令重排序 总结 内存可见性 volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色.同synch ...

  10. postman定义公共函数

    对于postman定义公共函数,相信很多小伙伴并不是很了解,下面给大家带来了一点福利,一起来看看吧.1.判断是否超时(assertNotTimeout)