文章目录
前言
在这篇文章中,重点掌握:
- SELECT 查询的基础语法;
- 如何排序检索数据;
- 什么情况下用 SELECT *,如何提升 SELECT 查询效率?
一、SELECT 的一些知识点
1. SELECT *
还是很有用的,这样我们就不需要写很长的 SELECT 语句了。但是在生产环境时要尽量避免使用SELECT*。原因是:这样做增加了数据库的负担。因为写清列名,可以减少数据表查询的网络传输量,而且考虑到在实际的工作中,我们往往不需要全部的列名,因此你需要养成良好的习惯,写出所需的列名。
2.起别名
一般来说起别名的作用是对原有名称进行简化,从而让 SQL 语句看起来更精简。同样我们也可以对表名称起别名,这个在多表连接查询的时候会用到。
3. 查询常数
SELECT '王者荣耀' as platform, name FROM heros
4. 去除重复行
关键字 DISTINCT 从结果中去掉重复的行。
这里有两点需要注意:
- DISTINCT 需要放到所有列名的前面,如果写成SELECT name, DISTINCT attack_range FROM heros会报错。
- DISTINCT 其实是对后面所有列名的组合进行去重,你能看到最后的结果是 69 条,因为这 69 个英雄名称不同,都有攻击范围(attack_range)这个属性值。如果你想要看都有哪些不同的攻击范围(attack_range),只需要写DISTINCT attack_range即可,后面不需要再加其他的列名了。
5. ORDER BY
使用 ORDER BY 子句有以下几个点需要掌握:
- 排序的列名:ORDER BY 后面可以有一个或多个列名,如果是多个列名进行排序,会按照后面第一个列先进行排序,当第一列的值相同的时候,再按照第二列进行排序,以此类推。
- 排序的顺序:ORDER BY 后面可以注明排序规则,ASC 代表递增排序,DESC 代表递减排序。如果没有注明排序规则,默认情况下是按照 ASC 递增排序。我们很容易理解 ORDER BY 对数值类型字段的排序规则,但如果排序字段类型为文本数据,就需要参考数据库的设置方式了,这样才能判断 A 是在 B 之前,还是在 B 之后。比如使用 MySQL 在创建字段的时候设置为 BINARY 属性,就代表区分大小写。
- 非选择列排序:ORDER BY 可以使用非选择列进行排序,所以即使在 SELECT 后面没有这个列名,你同样可以放到 ORDER BY 后面进行排序。
- ORDER BY 的位置:ORDER BY 通常位于 SELECT 语句的最后一条子句,否则会报错。
LIMIT
约束返回结果的数量。但不同数据库使用的关键字不同,这里略过。
HAVING
HAVING一般配合GROUP BY使用,作为筛选分组的条件。作用实际上和WHERE一样,都适用于限定条件。只是WHERE子句用于对查询结果的分组前,通过WHERE来过滤。而HAVING子句用于筛选满足条件的组,用于在分组之后进行过滤。
二、SELECT 的执行顺序
1. 关键字的顺序不能颠倒
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
2.SELECT 语句的执行顺序
FROM > WHERE > GROUP BY > HAVING > SELECT 的字段 > DISTINCT > ORDER BY > LIMIT
SQL执行原理(新知)
首先,你可以注意到,SELECT 是先执行 FROM 这一步的。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:
- 首先先通过 CROSS JOIN 求笛卡尔积,相当于得到虚拟表 vt(virtual table)1-1;
- 通过 ON 进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2;
- 添加外部行。如果我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3。
当然如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到是我们的原始数据。
当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1,就可以在此基础上再进行 WHERE 阶段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2。
然后进入第三步和第四步,也就是 GROUP 和 HAVING 阶段。在这个阶段中,实际上是在虚拟表 vt2 的基础上进行分组和分组过滤,得到中间的虚拟表 vt3 和 vt4。
当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 SELECT 和 DISTINCT 阶段。
首先在 SELECT 阶段会提取想要的字段,然后在 DISTINCT 阶段过滤掉重复的行,分别得到中间的虚拟表 vt5-1 和 vt5-2。
当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 ORDER BY 阶段,得到虚拟表 vt6。
最后在 vt6 的基础上,取出指定行的记录,也就是 LIMIT 阶段,得到最终的结果,对应的是虚拟表 vt7。
当然我们在写 SELECT 语句的时候,不一定存在所有的关键字,相应的阶段就会省略。
同时因为 SQL 是一门类似英语的结构化查询语言,所以我们在写 SELECT 语句的时候,还要注意相应的关键字顺序,所谓底层运行的原理,就是我们刚才讲到的执行顺序。