有关mysql中sql的执行顺序的小问题

 更新时间:2019年05月22日 08:42:20   作者:kobe_t  
在MySQL中我们可能会遇到一些关于执行顺序的问题,下面小编就来带大家了解一下原因以及如何解决

今天工作中碰到一个sql问题,关于left join的,后面虽然解决了,但是通过此问题了解了一下sql的执行顺序

场景还原

为避免安全纠纷,把场景模拟。

有一个学生表-S,一个成绩表G

CREATE TABLE `test_student` (
 `id` bigint(20) NOT NULL COMMENT '学号',
	`sex` TINYINT DEFAULT '0' COMMENT '性别 0-男 1-女',
 `name` varchar(255) DEFAULT NULL COMMENT '姓名'
) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='学生表';
 
CREATE TABLE `test_score` (
 `id` bigint(20) NOT NULL COMMENT '学号',
 `score` int NOT NULL COMMENT '分数',
	`level` TINYINT COMMENT '成绩 0-不及格 1-及格 2-优良 3-优秀'
) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='成绩表';
 
-- 初始化学生
INSERT INTO test_student VALUES(1, 0, '张三'), (2, 0, '李四'), (3, 1, '王X芳');
-- 初始化成绩
INSERT INTO test_score VALUES(1, 10, 0), (2, 20, 0), (3, 100, 3);

现在有一个需求,查出学生的考试成绩,可能的sql

SELECT ts.name AS '名字', tc.score AS '分数'
FROM test_student ts
LEFT JOIN test_score tc
ON ts.id = tc.s_id;

一切都很顺利,突然,刚考完试,就转来一个学生

INSERT INTO test_student VALUES(4, 0, '新来的');

他没成绩,还是刚才的sql查

老师只要看参加考试的学生的成绩,怎么办

1.用inner join

SELECT ts.name AS '名字', tc.score AS '分数'
FROM test_student ts
INNER JOIN test_score tc
ON ts.id = tc.s_id;

2.加条件过滤

SELECT ts.name AS '名字', tc.score AS '分数'
FROM test_student ts
LEFT JOIN test_score tc
ON ts.id = tc.s_id
AND tc.score is NOT NULL
;

发现加了条件过滤还是不对,额,改用where呢

SELECT ts.name AS '名字', tc.score AS '分数'
FROM test_student ts
LEFT JOIN test_score tc
ON ts.id = tc.s_id
WHERE tc.score is NOT NULL
;

bingo,那where为什么就对了呢。

这就涉及到sql的执行顺序了

where与join on

从上面的例子推断

where会从结果集中过滤出符合条件的记录,不符合条件的丢弃

join操作:有时为了得到完整的结果,我们需要从两个或更多的表中获取结果。我们就需要执行 join。

除了我们在上面的例子中使用的 INNER JOIN(内连接),我们还可以使用其他几种连接。

下面列出了您可以使用的 JOIN 类型,以及它们之间的差异。

  • JOIN: 如果表中有至少一个匹配,则返回行
  • LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
  • RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
  • FULL JOIN: 只要其中一个表中存在匹配,就返回行(mysql不支持,可以考虑用视图实现)

这里推荐一个写的通俗易懂的简单学习SQL的各种连接Join

sql顺序

从上面看到,在sql中,on是写在了where条件之前,那么数据库引擎分析执行sql时,是否on也是在where前面呢?

一般sql的写法顺序

1.SELECT [列名称 *代表所有的列]

2.FROM [表名称]

3.join_type JOIN [表名称]

4.ON [join条件]

5.WHERE [过滤条件]

6.GROUP BY [分组字段]

7.HAVING [分组条件]

8.ORDER BY [排序字段]

那么sql在执行时,顺序是怎样的呢?

标准的sql解析顺序为:

1.FROM    组装数据,来自不同数据源(表)

2.WHERE    根据条件过滤记录

3.GROUP BY 对数据分组

4.计算聚集函数,如avg,sum

5.使用HAVING子句筛选分组

6.计算所有表达式

7.使用ORDER BY对结果排序

那么sql的执行顺序呢?

1.FROM: 对前2个表执行笛卡尔积,生成虚表vt1

2.ON: 对vt1应用on条件,只有满足join_condition条件的才能插入虚表vt2

3.OUTER(join):如果指定了OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束

4.WHERE: 对vt3进行where筛选,只有满足where条件的才能插入vt4

5.GROUP BY: 对vt4按group by字段分组,得到vt5

6.HAVING:对vt5应用HAVING筛选器只有使 having_condition 为true的组才插入vt6

7.SELECT:处理select列表产生vt7

8.DISTINCT:将重复的行从vt7中去除产生vt8

9.ORDER BY:将vt8的行按order by子句中的列 列表排序生成一个游标vc9

10.LIMIT(Mysql): 从vc9的开始处选择指定数量的行生成vt10 并返回调用者

到了这里,应该发现,要写好sql不容易。但是了解了sql的执行顺序,能在开发的同理,更好的帮助写出好的程序。

比如join表不能太多(先过滤条件然后再根据表连接 同时在表中建立相关查询字段的索引这样在大数据多表联合查询的情况下速度相当快),这种sql优化问题,下次再学习整理下。

实践之!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • MySQL中查询字段为空或者为null的方法

    MySQL中查询字段为空或者为null的方法

    这篇文章主要介绍了MySQL中查询字段为空或者为null的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • mysql 5.6.13 免安装版配置方法详解

    mysql 5.6.13 免安装版配置方法详解

    这篇文章主要介绍了mysql 5.6.13 免安装版配置的方法,今天小编把配置方法分享到脚本之家平台供大家参考下
    2016-10-10
  • Mysql CONVERT函数的具体使用

    Mysql CONVERT函数的具体使用

    本文主要介绍了Mysql CONVERT函数的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 详解MySQL的数据行和行溢出机制

    详解MySQL的数据行和行溢出机制

    在前面的文章中,白日梦曾不止一次的提及到:InnoDB从磁盘中读取数据的最小单位是数据页。 而你想得到的id = xxx的数据,就是这个数据页众多行中的一行。 这篇文章我们就一起来看一下数据行设计的多么巧妙。
    2020-11-11
  • Mysql存储过程学习笔记--建立简单的存储过程

    Mysql存储过程学习笔记--建立简单的存储过程

    我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
    2014-08-08
  • 详解在MySQL中创建表的教程

    详解在MySQL中创建表的教程

    这篇文章主要介绍了详解在MySQL中创建表的教程,是MySQL入门学习中的基础知识,需要的朋友可以参考下
    2015-05-05
  • MySQL 日志相关知识总结

    MySQL 日志相关知识总结

    这篇文章主要介绍了MySQL 日志相关知识总结,帮助大家更好的理解和实用MySQL,感兴趣的朋友可以了解下
    2021-02-02
  • mysql 初始执行文件的使用介绍

    mysql 初始执行文件的使用介绍

    本文将详细介绍mysql 初始执行文件的使用方法,现在晒出来和大家分享下,希望可以帮助你们
    2012-11-11
  • CentOS系统中安装MySQL和开启MySQL远程访问的方法

    CentOS系统中安装MySQL和开启MySQL远程访问的方法

    这篇文章主要介绍了CentOS系统中安装MySQL和开启MySQL远程访问的方法,包括MySQL的随机启动等操作的介绍,需要的朋友可以参考下
    2016-02-02
  • mysql删除表数据如何恢复

    mysql删除表数据如何恢复

    这篇文章主要介绍了mysql删除表数据如何恢复,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11

最新评论