美文网首页
SQL必知必会(检索数据)

SQL必知必会(检索数据)

作者: 羋学僧 | 来源:发表于2021-08-03 19:36 被阅读0次

SELECT 查询的基础语法

创建了一个王者荣耀英雄数据表,这张表里一共有 69 个英雄,23 个属性值(不包括英雄名 name)


数据表中这 24 个字段(除了 id 以外),分别代表的含义见下图

一、查询列

SELECT name FROM heros;

对多个列进行检索,在列名之间用逗号 ,分割即可
SELECT name, hp_max, mp_max, attack_max, defense_max FROM heros;

使用 SELECT * 帮我们检索出所有的列
SELECT * FROM heros;

二、起别名

SELECT name AS n, hp_max AS hm, mp_max AS mm, attack_max AS am, defense_max AS dm FROM heros;

运行结果和上面多列检索的运行结果是一样的,只是将列名改成了 n、hm、mm、am 和 dm。当然这里的列别名只是举例,一般来说起别名的作用是对原有名称进行简化,从而让 SQL 语句看起来更精简。同样我们也可以对表名称起别名,这个在多表连接查询的时候会用到。

三、查询常数

SELECT 查询还可以对常数进行查询。对的,就是在 SELECT 查询结果中增加一列固定的常数列。这列的取值是我们指定的,而不是从数据表中动态取出的。你可能会问为什么我们还要对常数进行查询呢?SQL 中的 SELECT 语法的确提供了这个功能,一般来说我们只从一个表中查询数据,通常不需要增加一个固定的常数列,但如果我们想整合不同的数据源,用常数列作为这个表的标记,就需要查询常数。

比如说,我们想对 heros 数据表中的英雄名进行查询,同时增加一列字段platform,这个字段固定值为“王者荣耀”,可以这样写:

SELECT '王者荣耀' as platform, name FROM heros;

四、去除重复行

关于单个表的 SELECT 查询,还有一个非常实用的操作,就是从结果中去掉重复的行。使用的关键字是 DISTINCT。比如我们想要看下 heros 表中关于攻击范围的取值都有哪些:

SELECT DISTINCT attack_range FROM heros;

如果我们带上英雄名称,会是怎样呢:

SELECT DISTINCT attack_range, name FROM heros;
  • 1、DISTINCT 需要放到所有列名的前面,如果写成SELECT name, DISTINCT attack_range FROM heros会报错。
  • 2、DISTINCT 其实是对后面所有列名的组合进行去重,你能看到最后的结果是 69 条,因为这 69 个英雄名称不同,都有攻击范围(attack_range)这个属性值。如果你想要看都有哪些不同的攻击范围(attack_range),只需要写DISTINCT attack_range即可,后面不需要再加其他的列名了。

四、排序检索数据

使用 ORDER BY 子句有以下几个点需要掌握:

    1. 排序的列名:ORDER BY 后面可以有一个或多个列名,如果是多个列名进行排序,会按照后面第一个列先进行排序,当第一列的值相同的时候,再按照第二列进行排序,以此类推。
    1. 排序的顺序:ORDER BY 后面可以注明排序规则,ASC 代表递增排序,DESC 代表递减排序。如果没有注明排序规则,默认情况下是按照 ASC 递增排序。我们很容易理解 ORDER BY 对数值类型字段的排序规则,但如果排序字段类型为文本数据,就需要参考数据库的设置方式了,这样才能判断 A 是在 B 之前,还是在 B 之后。比如使用 MySQL 在创建字段的时候设置为 BINARY 属性,就代表区分大小写。
    1. 非选择列排序:ORDER BY 可以使用非选择列进行排序,所以即使在 SELECT 后面没有这个列名,你同样可以放到 ORDER BY 后面进行排序。
    1. ORDER BY 的位置:ORDER BY 通常位于 SELECT 语句的最后一条子句,否则会报错。

显示英雄名称及最大生命值,按照最大生命值从高到低的方式进行排序:

SELECT name, hp_max FROM heros ORDER BY hp_max DESC;

显示英雄名称及最大生命值,按照第一排序最大法力从低到高,当最大法力值相等的时候则按照第二排序进行,即最大生命值从高到低的方式进行排序:

SELECT name, hp_max FROM heros ORDER BY mp_max, hp_max DESC;

五、约束返回结果的数量

查询过程中,我们可以约束返回结果的数量,使用 LIMIT 关键字

SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5;

有一点需要注意,约束返回结果的数量,在不同的 DBMS 中使用的关键字可能不同。在 MySQL、PostgreSQL、MariaDB 和 SQLite 中使用 LIMIT 关键字,而且需要放到 SELECT 语句的最后面。如果是SQL Server 和 Access,需要使用TOP关键字,比如:

SELECT TOP 5 name, hp_max FROM heros ORDER BY hp_max DESC;

如果是 DB2,使用FETCH FIRST 5 ROWS ONLY这样的关键字:

SELECT name, hp_max FROM heros ORDER BY hp_max DESC FETCH FIRST 5 ROWS ONLY;

如果是 Oracle,你需要基于 ROWNUM 来统计行数:

SELECT name, hp_max FROM heros WHERE ROWNUM <=5 ORDER BY hp_max DESC;

需要说明的是,这条语句是先取出来前 5 条数据行,然后再按照 hp_max 从高到低的顺序进行排序。但这样产生的结果和上述方法的并不一样。我会在后面讲到子查询,你可以使用SELECT name, hp_max FROM (SELECT name, hp_max FROM heros ORDER BY hp_max) WHERE ROWNUM <=5得到与上述方法一致的结果。

约束返回结果的数量可以减少数据表的网络传输量,也可以提升查询效率。如果我们知道返回结果只有 1 条,就可以使用LIMIT 1,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回。

六、SELECT 的执行顺序

其中你需要记住 SELECT 查询时的两个顺序:

1. 关键字的顺序是不能颠倒的:

SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY 

2.SELECT 语句的执行顺序(在 MySQL 和 Oracle 中,SELECT 执行顺序基本相同):

FROM > WHERE > GROUP BY > HAVING > SELECT 的字段 > DISTINCT > ORDER BY > LIMIT

比如你写了一个 SQL 语句,那么它的关键字顺序和执行顺序是下面这样的:

SELECT DISTINCT player_id, player_name, count(*) as num # 顺序 5
FROM player JOIN team ON player.team_id = team.team_id # 顺序 1
WHERE height > 1.80 # 顺序 2
GROUP BY player.team_id # 顺序 3
HAVING num > 2 # 顺序 4
ORDER BY num DESC # 顺序 6
LIMIT 2 # 顺序 7

详细解释一下 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 语句的时候,还要注意相应的关键字顺序,所谓底层运行的原理,就是我们刚才讲到的执行顺序。

相关文章

  • SQL 学习笔记

    SQL基础 参考书籍: 《SQL必知必会》 检索数据 过滤数据 函数 分组数据 子查询 简单联结 法一: 法二: ...

  • SQL必知必会(检索数据)

    SELECT 查询的基础语法 创建了一个王者荣耀英雄数据表,这张表里一共有 69 个英雄,23 个属性值(不包括英...

  • SQL必知必会

    《SQL必知必会》SQL是使用 广泛的数据库语言,几乎所有重要的DBMS都支持SQL。《SQL必知必会(第4版)》...

  • SQL必知必会----第四版(一)

    记录自己学习这本书的过程此篇文章包括检索、排序检索数据和过滤数据 通往其他文章的入口:SQL必知必会----第四版...

  • MySql 插入数据

    插入数据 插入检索出来的数据 参考书籍: MySQL必知必会

  • 《SQL必知必会》—— 检索1

    普通检索 排序检索 过滤数据 通配符过滤(只能用于文本字段(字符串)) 计算字段 函数 汇总数据(不需要检索实际数...

  • 《SQL必知必会》—— 检索2

    子查询 联结表 组合查询

  • 《SQL必知必会》第2课 检索数据

    2.1 SELECT 语句 关键字(keyword)作为SQL 组成部分的保留字。关键字不能用作表或列的名字。附录...

  • 第二周学习总结

    本周继续学习了SQL必知必会这本书,从第2科开始,已学到第7课。本周主要学习了数据的检索和过滤。主要有如下收获: ...

  • 《SQL必知必会》笔记(MySQL实现)---检索数据(1)

    这篇主要讲的是检索一个或者多个列 SELECT语句 正如之前提到的,SQL语句是由简单的英语单词组成。这些单词被称...

网友评论

      本文标题:SQL必知必会(检索数据)

      本文链接:https://www.haomeiwen.com/subject/frdevltx.html