MySQL多表查询机制


Posted in MySQL onMarch 17, 2022

1. 前言

在SQL开发当中,多表联查是绝对绕不开的一种技能。同样的查询结果不同的写法其运行效率也是千差万别。

在实际开发当中,我见过(好像还写过~)不少又长又臭的查询SQL,数据量一上来查个十几分钟那是家常便饭。

因此,深入理解SQL的多表查询机制,少写一些慢查询,应该可以少挨点骂。

MySQL多表查询机制

2. 等值连接和非等值连接

2.1 等值连接

等值连接是在多表查询中最基础,也最简单的一种,其值为所有满足条件的笛卡尔积。

在from后面,哪个表写在前面结果中哪个表的值就先出现,

如下:

select *
from student,
     family
where student.family_id = family.id;

等值连接查询结果:

MySQL多表查询机制

阿里在最新发布的Java开发手册中强制要求,只要涉及多个表,必须在列名前加表的别名(或表名)进行限定

MySQL多表查询机制

2.2 非等值连接

非等值连接是通过a表中的值在b表中的某一个范围来进行的,能够很好的满足预设定好的分段统计需求。

非等值连接有两种写法,使用between...and...或大于号小于号

第一种写法:使用between...and...

select a.discipline_name, a.score, b.grade_tag
from achievement a,
     achievement_grade b
where a.score between b.lowest_score and b.highest_score;

第二种写法:使用>=<=

select a.discipline_name, a.score, b.grade_tag
from achievement a,
     achievement_grade b
where a.score >= b.lowest_score
  and a.score <= b.highest_score;

非等值连接查询结果:

MySQL多表查询机制

3. 自连接和非自连接

3.1 自连接

自连接,顾名思义就是同一张表自己跟自己连接,为了区分需要给表取不同的别名。如一张成绩表,需要查询所有分数比“语文”高的数据:

分数表:

MySQL多表查询机制

若不使用自连接,需要先通过查询语文的分数,然后再查询大于这个分数的数据。

具体可以按如下步骤进行查询:

-- 先查询语文的分数
select score from achievement where discipline_name = '语文';

-- 再查询分数比语文分数更高的数据
select * from achievement where score > 76;

而使用自连接,则可以在一条sq语句里完成查询:

select a.*
from achievement a,
     achievement b
where b.discipline_name = '语文'
  and a.score > b.score;

自连接查询结果:

MySQL多表查询机制

3.2 非自连接

除自连接外,其他的都叫非自连接~~~

4. 内连接和外连接

内连接和外连接的区分本质上是另一种分类方法,如内连接就是等值连接。

  • 内连接:合并具有同一列的两个或两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行
  • 外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的

行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。

  • 左外连接:连接条件中左边的表也称为主表 ,右边的表称为从表 。
  • 右外连接:连接条件中右边的表也称为主表 ,左边的表称为从表 。
  • 全外连接

4.1 测试数据

测试用学生表student和家庭表family数据如下:

学生表数据:

MySQL多表查询机制

家庭表数据:

MySQL多表查询机制

4.2 左外连接

-- 查出student中的所有数据,不满足的显示为null
-- 这里student在前面
select a.*
from student a
         left join family b on a.family_id = b.id

左外连接查询结果:

MySQL多表查询机制

4.3 右外连接

-- 查出student中的所有数据,不满足的显示为null
-- 这里student在后面
select a.*
from family b
         right join student a on b.id = a.family_id;

右外连接查询结果:

MySQL多表查询机制

4.4 全外连接

很遗憾,MySQL不支持全外连接。

附录:测试数据SQL脚本

-- auto-generated definition
create table student
(
    id           int auto_increment
        primary key,
    student_id   int                                null comment '学号',
    student_name varchar(40)                        null comment '姓名',
    family_id    int                                null comment '家庭ID',
    create_time  datetime default CURRENT_TIMESTAMP null comment '创建时间'
)
    comment '学生表';

create table family
(
    id             int auto_increment
        primary key,
    family_name    varchar(40)                        null comment '家庭名称',
    family_address varchar(40)                        null comment '家庭地址',
    create_time    datetime default CURRENT_TIMESTAMP null comment '创建时间'
)
    comment '家庭表';

create table achievement
(
    id              int auto_increment
        primary key,
    score           int         null comment '分数',
    discipline_name varchar(40) null comment '学科名称',
    student_id      int         null comment '学号'
)
    comment '成绩表';

create table achievement_grade
(
    id            int auto_increment
        primary key,
    grade_tag     varchar(10)                        null comment '档次',
    lowest_score  int                                null comment '最低分',
    highest_score int                                null comment '最高分',
    create_time   datetime default CURRENT_TIMESTAMP null comment '创建时间'
)
    comment '分数档次表';

INSERT INTO achievement_grade (id, grade_tag, lowest_score, highest_score, create_time) VALUES (1, '不及格', 0, 60, '2022-03-02 11:44:01');
INSERT INTO achievement_grade (id, grade_tag, lowest_score, highest_score, create_time) VALUES (2, '良好', 60, 80, '2022-03-02 11:44:01');
INSERT INTO achievement_grade (id, grade_tag, lowest_score, highest_score, create_time) VALUES (3, '优秀', 80, 100, '2022-03-02 11:44:01');

INSERT INTO student (id, student_id, student_name, family_id, create_time) VALUES (1, 1, '张三', 1, '2022-03-02 09:55:01');
INSERT INTO student (id, student_id, student_name, family_id, create_time) VALUES (2, 2, '李四', 2, '2022-03-02 09:55:01');
INSERT INTO student (id, student_id, student_name, family_id, create_time) VALUES (3, 3, '王五', 3, '2022-03-02 09:55:01');
INSERT INTO student (id, student_id, student_name, family_id, create_time) VALUES (4, 4, '高飞', null, '2022-03-02 19:45:14');

INSERT INTO family (id, family_name, family_address, create_time) VALUES (1, '张三家', '北京', '2022-03-02 09:54:13');
INSERT INTO family (id, family_name, family_address, create_time) VALUES (2, '李四家', '上海', '2022-03-02 09:54:13');
INSERT INTO family (id, family_name, family_address, create_time) VALUES (3, '王五家', '西伯利亚', '2022-03-02 09:54:13');

INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (1, 76, '语文', 1);
INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (2, 80, '数学', 1);
INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (3, 65, '英语', 1);
INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (4, 98, '地理', 1);
INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (5, 77, '历史', 1);
INSERT INTO achievement (id, score, discipline_name, student_id) VALUES (6, 69, '生物', 1);

到此这篇关于MySQL多表查询机制的文章就介绍到这了,更多相关MySQL多表查询内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
Idea连接MySQL数据库出现中文乱码的问题
Apr 14 MySQL
MySQL表字段时间设置默认值
May 13 MySQL
MySQL之PXC集群搭建的方法步骤
May 25 MySQL
MySQL 如何设计统计数据表
Jun 15 MySQL
SQL实现LeetCode(180.连续的数字)
Aug 04 MySQL
MySQL命令无法输入中文问题的解决方式
Aug 30 MySQL
分享MySQL常用 内核 Debug 几种常见方法
Mar 17 MySQL
Linux系统下MySQL配置主从分离的步骤
Mar 21 MySQL
MySQL视图概念以及相关应用
Apr 19 MySQL
MySQL中EXPLAIN语句及用法
May 20 MySQL
MySQL数据库如何查看表占用空间大小
Jun 10 MySQL
MySQL中TIMESTAMP类型返回日期时间数据中带有T的解决
Dec 24 MySQL
MySQL高级进阶sql语句总结大全
Mar 16 #MySQL
一条慢SQL语句引发的改造之路
MySQL中一条update语句是如何执行的
关于k8s环境部署mysql主从的问题
Mar 13 #MySQL
MYSQL如何查看进程和kill进程
Mar 13 #MySQL
一次SQL如何查重及去重的实战记录
Mar 13 #MySQL
面试提问mysql一张表到底能存多少数据
You might like
用PHP查询域名状态whois的类
2006/11/25 PHP
如何让thinkphp在模型中自动完成session赋值小教程
2014/09/05 PHP
php中将一个对象保存到Session中的方法
2015/03/13 PHP
yii2带搜索功能的下拉框实例详解
2016/05/12 PHP
Mootools 1.2教程 输入过滤第二部分(字符串)
2009/09/15 Javascript
JavaScript中setFullYear()方法的使用详解
2015/06/11 Javascript
JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
2015/09/24 Javascript
js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)
2015/11/09 Javascript
AngularJS基于ui-route实现深层路由的方法【路由嵌套】
2016/12/14 Javascript
easyUI实现类似搜索框关键词自动提示功能示例代码
2016/12/27 Javascript
Bootstrap按钮组简单实现代码
2017/03/06 Javascript
bootstrap+jQuery实现的动态进度条功能示例
2017/05/25 jQuery
jquery中ajax请求后台数据成功后既不执行success也不执行error的完美解决方法
2017/12/24 jQuery
vue移动端弹框组件的实例
2018/09/25 Javascript
vue使用swiper实现中间大两边小的轮播图效果
2019/11/24 Javascript
原生js实现移动小球(碰撞检测)
2020/12/17 Javascript
使用python实现拉钩网上的FizzBuzzWhizz问题示例
2014/05/05 Python
Python中动态获取对象的属性和方法的教程
2015/04/09 Python
python视频按帧截取图片工具
2019/07/23 Python
关于Python3 类方法、静态方法新解
2019/08/30 Python
Windows10下 python3.7 安装 facenet的教程
2019/09/10 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
Html5实现首页动态视频背景的示例代码
2019/09/25 HTML / CSS
阿迪达斯芬兰官方网站:adidas芬兰
2017/01/30 全球购物
Ellesse英国官网:意大利高级运动品牌
2019/07/23 全球购物
个人找工作的自我评价
2013/10/17 职场文书
公司周年庆活动方案
2014/08/25 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
纪念九一八事变演讲稿:青少年应树立远大理想
2014/09/14 职场文书
2014年大学班级工作总结
2014/11/14 职场文书
人事聘任通知
2015/04/21 职场文书
小学安全教育主题班会
2015/08/12 职场文书
演讲稿:态度决定一切
2019/04/02 职场文书
Nginx反向代理及负载均衡如何实现(基于linux)
2021/03/31 Servers
Python实现简单的俄罗斯方块游戏
2021/09/25 Python