mysql内连接查询原理_MySQL全面瓦解12:连接查询的原理和应用

概述

MySQL最强大的功能之一就是能在数据检索的执行中连接(join)表。大部分的单表数据查询并不能满足我们的需求,这时候我们就需要连接一个或者多个表,并通过一些条件过滤筛选出我们需要的数据。

了解MySQL连接查询之前我们先来理解下笛卡尔积的原理。

数据准备

依旧使用上节的表数据(包含classes 班级表和students 学生表):

1 mysql> select * fromclasses;2 +---------+-----------+

3 | classid | classname |

4 +---------+-----------+

5 | 1 | 初三一班 |

6 | 2 | 初三二班 |

7 | 3 | 初三三班 |

8 | 4 | 初三四班 |

9 +---------+-----------+

10 4 rows in set

11

12 mysql> select * fromstudents;13 +-----------+-------------+-------+---------+

14 | studentid | studentname | score | classid |

15 +-----------+-------------+-------+---------+

16 | 1 | brand | 97.5 | 1 |

17 | 2 | helen | 96.5 | 1 |

18 | 3 | lyn | 96 | 1 |

19 | 4 | sol | 97 | 1 |

20 | 7 | b1 | 81 | 2 |

21 | 8 | b2 | 82 | 2 |

22 | 13 | c1 | 71 | 3 |

23 | 14 | c2 | 72.5 | 3 |

24 | 19 | lala | 51 | 0 |

25 +-----------+-------------+-------+---------+

26 9 rows in set

笛卡尔积

笛卡尔积:也就是笛卡尔乘积,假设两个集合A和B,笛卡尔积表示A集合中的元素和B集合中的元素任意相互关联产生的所有可能的结果。

比如A中有m个元素,B中有n个元素,A、B笛卡尔积产生的结果有m*n个结果,相当于循环遍历两个集合中的元素,任意组合。

笛卡尔积在SQL中的实现方式既是交叉连接(Cross Join)。所有连接方式都会先生成临时笛卡尔积表,笛卡尔积是关系代数里的一个概念,表示两个表中的每一行数据任意组合。

所以上面的表就是 4(班级表)* 9(学生表) = 36条数据;

笛卡尔积语法格式:

1 select cname1,cname2,... fromtname1,tname2,...;2 or3 select cname from tname1 join tname2 [join tname...];

图例表示:

361aa287be9cf5b57797440a292842b1.png

上述两个表实际执行结果如下:

1 mysql> select * from classes a,students b order bya.classid,b.studentid;2 +---------+-----------+-----------+-------------+-------+---------+

3 | classid | classname | studentid | studentname | score | classid |

4 +---------+-----------+-----------+-------------+-------+---------+

5 | 1 | 初三一班 | 1 | brand | 97.5 | 1 |

6 | 1 | 初三一班 | 2 | helen | 96.5 | 1 |

7 | 1 | 初三一班 | 3 | lyn | 96 | 1 |

8 | 1 | 初三一班 | 4 | sol | 97 | 1 |

9 | 1 | 初三一班 | 7 | b1 | 81 | 2 |

10 | 1 | 初三一班 | 8 | b2 | 82 | 2 |

11 | 1 | 初三一班 | 13 | c1 | 71 | 3 |

12 | 1 | 初三一班 | 14 | c2 | 72.5 | 3 |

13 | 1 | 初三一班 | 19 | lala | 51 | 0 |

14 | 2 | 初三二班 | 1 | brand | 97.5 | 1 |

15 | 2 | 初三二班 | 2 | helen | 96.5 | 1 |

16 | 2 | 初三二班 | 3 | lyn | 96 | 1 |

17 | 2 | 初三二班 | 4 | sol | 97 | 1 |

18 | 2 | 初三二班 | 7 | b1 | 81 | 2 |

19 | 2 | 初三二班 | 8 | b2 | 82 | 2 |

20 | 2 | 初三二班 | 13 | c1 | 71 | 3 |

21 | 2 | 初三二班 | 14 | c2 | 72.5 | 3 |

22 | 2 | 初三二班 | 19 | lala | 51 | 0 |

23 | 3 | 初三三班 | 1 | brand | 97.5 | 1 |

24 | 3 | 初三三班 | 2 | helen | 96.5 | 1 |

25 | 3 | 初三三班 | 3 | lyn | 96 | 1 |

26 | 3 | 初三三班 | 4 | sol | 97 | 1 |

27 | 3 | 初三三班 | 7 | b1 | 81 | 2 |

28 | 3 | 初三三班 | 8 | b2 | 82 | 2 |

29 | 3 | 初三三班 | 13 | c1 | 71 | 3 |

30 | 3 | 初三三班 | 14 | c2 | 72.5 | 3 |

31 | 3 | 初三三班 | 19 | lala | 51 | 0 |

32 | 4 | 初三四班 | 1 | brand | 97.5 | 1 |

33 | 4 | 初三四班 | 2 | helen | 96.5 | 1 |

34 | 4 | 初三四班 | 3 | lyn | 96 | 1 |

35 | 4 | 初三四班 | 4 | sol | 97 | 1 |

36 | 4 | 初三四班 | 7 | b1 | 81 | 2 |

37 | 4 | 初三四班 | 8 | b2 | 82 | 2 |

38 | 4 | 初三四班 | 13 | c1 | 71 | 3 |

39 | 4 | 初三四班 | 14 | c2 | 72.5 | 3 |

40 | 4 | 初三四班 | 19 | lala | 51 | 0 |

41 +---------+-----------+-----------+-------------+-------+---------+

42 36 rows in set

这样的数据肯定不是我们想要的,在实际应用中,表连接时要加上限制条件,才能够筛选出我们真正需要的数据。

我们主要的连接查询有这几种:内连接、左(外)连接、右(外)连接,下面我们一 一来看。

内连接查询 inner join

语法格式:

1 select cname from tname1 inner join tname2 on joincondition;2 或者3 select cname from tname1 join tname2 on joincondition;4 或者5 select cname from tname1,tname2 [where join condition];

说明:在笛卡尔积的基础上加上了连接条件,组合两个表,返回符合连接条件的记录,也就是返回两个表的交集(阴影)部分。如果没有加上这个连接条件,就是上面笛卡尔积的结果。

15e8dce35737248a6e69c88bf93cd3ba.png

1 mysql> select a.classname,b.studentname,b.score from classes a inner join students b on a.classid =b.classid;2 +-----------+-------------+-------+

3 | classname | studentname | score |

4 +-----------+-------------+-------+

5 | 初三一班 | brand | 97.5 |

6 | 初三一班 | helen | 96.5 |

7 | 初三一班 | lyn | 96 |

8 | 初三一班 | sol | 97 |

9 | 初三二班 | b1 | 81 |

10 | 初三二班 | b2 | 82 |

11 | 初三三班 | c1 | 71 |

12 | 初三三班 | c2 | 72.5 |

13 +-----------+-------------+-------+

14 8 rows in set

从上面的数据可以看出 ,初三四班 classid = 4,因为没有关联的学生,所以被过滤掉了;lala 同学的classid=0,没法关联到具体的班级,也被过滤掉了,只取两表都有的数据交集

1 mysql> select a.classname,b.studentname,b.score from classes a,students b where a.classid = b.classid and a.classid=1;2 +-----------+-------------+-------+

3 | classname | studentname | score |

4 +-----------+-------------+-------+

5 | 初三一班 | brand | 97.5 |

6 | 初三一班 | helen | 96.5 |

7 | 初三一班 | lyn | 96 |

8 | 初三一班 | sol | 97 |

9 +-----------+-------------+-------+

10 4 rows in set

查找1班同学的成绩信息,上面语法格式的第三种,这种方式简洁高效,直接在连接查询的结果后面进行Where条件筛选。

左连接查询 left join

left join on / left outer join on,语法格式:

1 select cname from tname1 left join tname2 on join condition;

说明: left join 是left outer join的简写,全称是左外连接,外连接中的一种。 左(外)连接,左表(classes)的记录将会全部出来,而右表(students)只会显示符合搜索条件的记录。右表无法关联的内容均为null。

421e149c6e2dc66026254e3618f119cb.png

1 mysql> select a.classname,b.studentname,b.score from classes a left join students b on a.classid =b.classid;2 +-----------+-------------+-------+

3 | classname | studentname | score |

4 +-----------+-------------+-------+

5 | 初三一班 | brand | 97.5 |

6 | 初三一班 | helen | 96.5 |

7 | 初三一班 | lyn | 96 |

8 | 初三一班 | sol | 97 |

9 | 初三二班 | b1 | 81 |

10 | 初三二班 | b2 | 82 |

11 | 初三三班 | c1 | 71 |

12 | 初三三班 | c2 | 72.5 |

13 | 初三四班 | NULL | NULL |

14 +-----------+-------------+-------+

15 9 rows in set

从上面结果中可以看出,初三四班无法找到对应的学生,所以后面两个字段使用null标识。

右连接查询 right join

right join on / right outer join on,语法格式:

1 select cname from tname1 right join tname2 on join condition;

说明:right join是right outer join的简写,全称是右外连接,外连接中的一种。与左(外)连接相反,右(外)连接,左表(classes)只会显示符合搜索条件的记录,而右表(students)的记录将会全部表示出来。左表记录不足的地方均为NULL。

9ed9cebe36c2fa456e9833ad3db06feb.png

1 mysql> select a.classname,b.studentname,b.score from classes a right join students b on a.classid =b.classid;2 +-----------+-------------+-------+

3 | classname | studentname | score |

4 +-----------+-------------+-------+

5 | 初三一班 | brand | 97.5 |

6 | 初三一班 | helen | 96.5 |

7 | 初三一班 | lyn | 96 |

8 | 初三一班 | sol | 97 |

9 | 初三二班 | b1 | 81 |

10 | 初三二班 | b2 | 82 |

11 | 初三三班 | c1 | 71 |

12 | 初三三班 | c2 | 72.5 |

13 | NULL | lala | 51 |

14 +-----------+-------------+-------+

15 9 rows in set

从上面结果中可以看出,lala同学无法找到班级,所以班级名称字段为null。

连接查询+聚合函数

使用连接查询的时候,经常会配合使用聚集函数来进行数据汇总。比如在上面的数据基础上查询出每个班级的人数和平均分数、班级总分数。

1 mysql> select a.classname as '班级名称',count(b.studentid) as '总人数',sum(b.score) as '总分',avg(b.score) as '平均分'

2 from classes a inner join students b on a.classid =b.classid3 group by a.classid,a.classname;4 +----------+--------+--------+-----------+

5 | 班级名称 | 总人数 | 总分 | 平均分 |

6 +----------+--------+--------+-----------+

7 | 初三一班 | 4 | 387.00 | 96.750000 |

8 | 初三二班 | 2 | 163.00 | 81.500000 |

9 | 初三三班 | 2 | 143.50 | 71.750000 |

10 +----------+--------+--------+-----------+

11 3 rows in set

这边连表查询的同时对班级(classid,classname)做了分组,并输出每个班级的人数、平均分、班级总分。

连接查询附加过滤条件

使用连接查询之后,大概率会对数据进行在过滤筛选,所以我们可以在连接查询之后再加上where条件,比如我们根据上述的结果只取出一班的同学信息。

1 mysql> select a.classname,b.studentname,b.score from classes a inner join students b on a.classid = b.classid where a.classid=1;2 +-----------+-------------+-------+

3 | classname | studentname | score |

4 +-----------+-------------+-------+

5 | 初三一班 | brand | 97.5 |

6 | 初三一班 | helen | 96.5 |

7 | 初三一班 | lyn | 96 |

8 | 初三一班 | sol | 97 |

9 +-----------+-------------+-------+

10 4 rows in set

如上,只输出一班的同学,同理,可以附件 limit 限制,order by排序等操作。

总结

1、连接查询必然要带上连接条件,否则会变成笛卡尔乘积数据,使用不正确的联结条件,也将返回不正确的数据。

2、SQL规范推荐首选INNER JOIN语法。但是连接的几种方式本身并没有明显的性能差距,性能的差距主要是由数据的结构、连接的条件,索引的使用等多种条件综合决定的。

我们应该根据实际的业务场景来决定,比如上述数据场景:如果要求返回返回有学生的班级就使用 inner join;如果必须输出所有班级则使用left join;如果必须输出所有学生,则使用right join。

3、性能上的考虑,MySQL在运行时会根据关联条件处理连接的表,这种处理可能是非常耗费资源的,连接的表越多,性能下降越厉害。所以要分析去除那些不必要的连接和不需要显示的字段。

之前我的项目团队在优化旧的业务代码时,发现随着业务的变更,某些数据不需要显示,对应的某个连接也不需要了,去掉之后,性能较大提升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304135.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 .NET 中使用 Kafka

Kafka 是一个开源的,分布式的,可扩展的,高性能的发布订阅模式的消息中间件,如果你要构建一个处理海量数据的系统,那么 Kafka 将会是一个非常好的选择,这篇文章我们将会讨论如何基于 Kakfa 构建一个发布订阅…

傅里叶变换和拉普拉斯变换的物理解释及区别

傅里叶变换在物理学、数论、组合数学、信号处理、概率论、统计学、密码学、声学、光学、海洋学、结构动力学等领域都有着广泛的应用(例如在信号处理中,傅里叶变换的典型用途是将信号分解成幅值分量和频率分量)。傅里叶变换能将满足一定条件的…

Teleport 开源堡垒机的使用

公司的服务器可能会存在这样一种情况,具体的应用是部署在一个或多个内网服务器上,然后由一台外网服务器通过代理的方式对外提供服务,例如下图:我们如果需要进入到内网服务器进行操作就必须先要进入外网服务器,然后再远…

python拼图游戏_乐趣无穷的Python课堂

Python world/特慧编/你所认为的.........pythonpython&枯燥、无趣boring“安全”提示走进特慧编走进“python编程课”让我们进入真正的编程世界,培养逻辑数理思维,学习掌握python特色,让你的学习过程不再枯燥、不再无趣~~~下面跟着我的脚…

让 Python 更加充分的使用 Sqlite3

我最近在涉及大量数据处理的项目中频繁使用 sqlite3。我最初的尝试根本不涉及任何数据库,所有的数据都将保存在内存中,包括字典查找、迭代和条件等查询。这很好,但可以放入内存的只有那么多,并且将数据从磁盘重新生成或加载到内存…

techempower之Plaintext上7百万RPS

在Plaintext这项测试中第一阶梯的分隔线基本算是7百万RPS,Beetlex并没有到到这一阶梯停留在69X万RPS处,虽然只差那数万但在排名上让人感觉不爽。Beetlex在很多项测都微微领先aspcore,但在最基础项落下一点点的确让我感觉到不太满意,更希望Bee…

详解全排列算法

简介给定 {1, 2, 3, , , n},其全排列为 n! 个,这是最基础的高中组合数学知识。我们以 n4 为例,其全部排列如下图(以字典序树形式来呈现):我们很容易想到用递归来求出它的所有全排列。仔细观察上图&#xff…

VS2019 调试技巧之附加进程

C# 创建服务并附加到进程进行调试步骤一:在任务栏右键-》》点击任务管理器-》》选择服务,找到启动的进程PID或者WINR 进入cmd命令 输入 netstat -ano | find "进程端口" 找端口步骤二:VS中找到“调试”菜单,选择“…

sql同时向两个表插入数据_SQL入门-数据库和客户端的安装,表的创建和数据插入...

1、如何验证MySQL数据库安装成功按照上图操作打开SQL命令行客户端输入安装MySQL时设置的密码并按enter键,得到下图:如果有显示出来红框里的内容,就表示安装成功。红框里的内容表示的是MySQL数据库版本号。2、如何用客户端(Navicat…

我是怎么进入Oracle这样的大企业的?

导语:人工智能是泡沫么?AI产业的未来将何去何从?机器学习又该怎么学习?AI行业从业者又是怎么看待这个行业的呢?踏入一个行业之前最好对这个行业有个全方位的了解。本文作者饶毅,现就职于甲骨文公司。AI行业…

websocket文档_WebSocket推送 原理扫盲到上手实践

关于服务端推送技术,大家比较熟悉的可能就是轮询,但是轮询只能是由客户端先发起http请求。在HTTP1.1中的keep-alive方式建立的http连接,但是一个Request只能对应一个Response,而且这个Response是被动的,不能主动发起。…

DISCUZ7.2在通达OA2009桌面显示技巧

最近在测试DISCUZ 和通达...猛然间看到,,,可以DISCUZ可以和通达完美结合,禁不住进行了测试.....效果还挺好的...最初效果图如下:感觉挺别扭的,于是将DISCUZ调用代码更改了代码如下:[show1] <table width"100%" > <tr> <td alignleft> <di…

如何在 ASP.Net Core 中使用 Lamar

ASP.Net Core 自带了一个极简的 开箱即用 的依赖注入容器&#xff0c;实际上&#xff0c;你还可以使用第三方的 依赖注入容器 来替代它&#xff0c;依赖注入是一种设计模式&#xff0c;它能够有效的实现对象之间的解耦并有利于提高单元测试和维护性&#xff0c;你可以使用 依赖…

扎克伯格做了26张PPT,员工效率提10倍,已被疯狂传阅!

1、时间常有&#xff0c;时间在于优先。2、时间总会有的&#xff1a;每天只计划 4&#xff5e;5 小时真正的工作。3、当你在状态时&#xff0c;就多干点&#xff1b;不然就好好休息&#xff1a;有时候会连着几天不是工作状态&#xff0c;有时在工作状态时却又能天天忙活 12 小时…

2010南非世界杯32强手绘海报

2010南非世界杯32强手绘海报 2010年南非世界杯已经进入最后的倒计时&#xff0c;近日&#xff0c;ESPN推出了一组以世界杯32强为主题的手绘海报。在这组颇有漫画性质的海报中&#xff0c;32强每支球队的特点都是展现得淋淋尽致&#xff0c;卡卡、梅西、C罗、托雷斯等球星也自然…

鹅厂二面,Nginx回忆录

上周二面鹅厂&#xff0c;面试官问出了“nginx你了解吗&#xff1f;”这样宽泛直白的句式&#xff0c;我一时抓不到重点&#xff0c;一时语噻。下班想了一下&#xff0c;平时潜移默化用到不少nginx的能力&#xff0c;但在面试的时候没有吹成对应的概念。面谈nginx核心能力nginx…

干货|吴恩达Coursera课程教你学习神经网络二!

上一周的课程中讲了神经网络的结构以及正向传播(feed forward)过程&#xff0c;了解了神经网络是如何进行预测的&#xff0c;但是预测的结果怎么和真是结果进行比较以及发现了错误如何修改还没有提及。这一周的课程中&#xff0c;介绍了cost function作为结果比较的标准以及bac…

vue预加载动态生成runtime.js_预渲染 prerender-spa-plugin 避坑指南

预渲染原理在webpack打包结束并生成文件后&#xff08;after-emit hook&#xff09;&#xff0c;会启动一个server模拟网站的运行&#xff0c;用puppeteer&#xff08;google官方的headless 无头浏览器浏览器&#xff09;访问指定的页面route&#xff0c;得到相应的html结构&am…

使用 .NET CLI 构建项目脚手架

前言在微服务场景中&#xff0c;开发人员分配到不同的小组&#xff0c;系统会拆分为很多个微服务&#xff0c;有一点是&#xff0c;每个项目都需要单元测试&#xff0c;接口文档&#xff0c;WebAPI接口等&#xff0c;创建新项目这些都是重复的工作&#xff0c;而且还要保证各个…