SQL语句连接筛选条件放在on和where后的区别(一篇足矣)

2023-10-27

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过程中出现的莫名其妙的错误。

加油吧,测试人!路就在脚下,成功就在明天!

未来的你肯定会感谢现在拼命的自己!

给大家推荐一个软件测试技术交流群:810119819 群友福利免费领取

愿你我相遇,皆有所获! 欢迎关注微信公众号:程序员阿沐

1.免费领取一份216页软件测试工程师面试宝典文档资料。

2.软件测试学习路线以及相对应的视频学习教程免费分享!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL语句连接筛选条件放在on和where后的区别(一篇足矣) 的相关文章

随机推荐

  • hashmap底层以及红黑树 终于懂了!!!

    目录 0 引言 1 红黑树 0 引言 jdk 1 7里面 HashMap中的数据结构是数组 单链表的组合 以键值对 key value 的形式存储元素的 通过put 和get 方法储存和获取对象 在JDK1 6 JDK1 7中 HashMa
  • openwrt--uci指令的使用

    UCI简介 UCI是集中式配置信息管理接口 Unified Configuration Interface 的缩写 他是OpenWrt引进的一套配置参数管理系统 UCI管理了OpenWrt下最主要的系统配置参数并且提供了简单 容易 标准化的
  • JAVA零基础学习课程个人笔记(全手打)

    目录 chapter01 Chapter02 目录 Chapter02 Day05 07 方法 Method 课堂笔记 chapter02 控制循环中断继续语句 chapter03 0 面向对象 chapter03 1 封装 chapter
  • 再见前端!纯Java撸个管理系统,这框架用起来贼爽!

    摘要 一个管理系统 往往需要后端 前端一起实现 单表CRUD操作往往都差不多 我们可以使用代码生成器来实现 有时候我们的管理系统只需要一些简单的CRUD页面 有没有什么框架能做到不写前端代码 纯Java撸个管理系统呢 这里推荐一个全栈类框架
  • golang通过代理访问url

    直接上实例 命令测试 curl proxy 10 0 55 22 8080 v http www baidu com package main import fmt io ioutil net http net url net time f
  • Parcel是如何存储数据

    Parcel学习 Parcel是如何存储数据的 第一步 第二步 第三步 如何读取呢 Parcel和serializable Parcel是如何存储数据的 疑问 平时java使用它进行序列化要关注的点就是读写顺序 为什么要注意读写顺序呢 在这
  • python基础十一:异常处理以及文件操作

    1 异常 1 1异常简介 程序在运行过程中可能会出现一些错误 比如 使用了不存在的索引 两个不同类型的数据相加 这些错误我们称之为异常 处理异常 程序运行时出现异常 目的并不是让我们的程序直接终止 Python是希望在出现异常时 我们可以编
  • 前端js计算导致的精度问题解决方案

    前言 js计算会导致很多奇奇怪怪的问题 这是由于js使用二进制 有一些浮点数用二进制表示时是无穷的 而为节省存储空间只存储64位 精度丢失从而导致计算出现问题 一 写个方法 自己写一个方法来解决 二 使用插件 使用 number preci
  • (二)ChatGLM-6B模型部署以及ptuning微调详细教程

    文章目录 介绍什么是ChatGLM 6B Torch 安装ChatGLM 6B模型 安装过程 Ptuning微调 安装过程 初始化环境 训练 准备自己的数据集 推理 验证 问题和思考 泛化学习 simbert 不属于必学 介绍什么是Chat
  • CSS Modules

    CSS Modules CSS模块 对CSS进行模块化处理 目的 解决在 React 开发时 组件之间类名重复导致的样式冲突问题 使用后 会自动生成类名 类名格式 filename classname hash filename 文件名 c
  • 华为防火墙IPsec点对点配置解析

    一 完成基本互联 主机直连的接口为trust区域 防火墙之间互联的接口为untrust区域 二 左边的防火墙IPsec的配置 1 Ike Proposal 的创建 ike proposal xx 首先创建ike proposal xx 这一
  • 在PHP脚本中的转义字符 \

    在编写PHP脚本的过程中 经常在遇到写路径或者某些特殊字符时 要用到转义字符 反斜线 比如 在使用fopen 函数的时候 我们要写参数 即要打开的路径 fp fopen DOCUMENT ROOT orders orders txt w 在
  • Triangle Tessellation with OpenGL 4.0

    FROM http prideout net blog p 48 This is the first of a two part article on tessellation shaders with OpenGL 4 0 This en
  • AVPlayer 视频播放

    1 AVPlayer AVPlayer 是一个用来播放基于时间的视听媒体的控制器对象 一个队播放和资源时间相隔信息进行管理的对象 而非一个视图或窗口控制器 AVPlayer支持播放从本地 分步下载或通过HTTP Live Streaming
  • 2023版golang面试题100道(map)

    面试题合集目录 map查找 假设当前 B 4 即桶数量为2 B 16个 要从map中获取k4对应的value 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 k4的查找步骤 计算k4的hash值 通过低B位来确定在哪号桶
  • 静态代码和动态代码的区别_静态和动态代码分析之间有什么区别,您如何知道使用哪个?...

    让我们从一个运动类比开始 以帮助说明这两种方法之间的差异 静态代码分析类似于练习网和投球机练习棒球挥杆 最小的惊喜 经过几次挥杆后 您每次都知道球的确切位置 这有助于处理基础知识并确保您拥有良好的形式 虽然这有助于改善你的游戏 但它只能让你
  • 订单管理系统

    本专栏介绍了使用Qt开发的一些小型桌面软件 其中包括软件功能介绍 软件截图 主要代码等内容 此外 本专栏还提供完整的软件源码和安装包供有需要的同学下载 我的目标是开发一些简洁美观且实用的客户端小软件 如果能够为大家提供有用的软件或对学习有益
  • Hypertable 快速安装,仅需上载一个RPM包,零编译

    Hypertable 快速安装 仅需上载一个RPM包 零编译 Hypertable 快速安装 仅需下载一个RPM包 零编译 本文采用 单机安装 1 Hypertable 安装 Hypertable 的几种安装方式 单机 安装于单机 采用本地
  • Arduino core for the ESP32 安装失败问题处理方法

    文章目录 目的 离线开发板数据包 鱼 安装最新开发板数据包 渔 总结 目的 理论上Arduino IDE安装开发板数据包是非常方便的 不过在国内的网络环境下有时候就会很纠结 另外Arduino IDE对于下载数据这块也存在问题 经常下着下着
  • SQL语句连接筛选条件放在on和where后的区别(一篇足矣)

    sql查询这个东西 要说它简单 可以很简单 通常情况下只需使用增删查改配合编程语言的逻辑表达能力 就能实现所有功能 但是增删查改并不能代表sql语句的所有 完整的sql功能会另人望而生畏 就拿比普通增删查改稍微复杂一个层次的连接查询来说 盲