【Mysql面试宝典】快速上手Mysql查询(上)
写在前面,大家好!我是【跨考菌】,一枚跨界的程序猿,专注于后台技术的输出,目标成为
全栈攻城狮
!这博客是对我跨界过程的总结和思考。如果你也对Java
、后端技术
感兴趣,抑或是正在纠结于跨界,都可以关注我的动态,让我们一起学习,一起进步~
我的博客地址为:【跨考菌】的博客
上文【Mysql面试宝典】快速搞定Mysql表操作介绍了Mysql表结构的相关操作命令。本文开始介绍Mysql查询指令。和【跨考菌】一起加油吧~
1、前文回顾
上文【Mysql面试宝典】快速搞定Mysql表操作我们唠叨了数据库的创建、选择和删除,表的创建、修改和删除以及简单的查询和插入命令。但是这只是搭建了一个空架子,其实对于MySQL
来说,我们平时使用频率最高的还是查询功能
,本篇将详细聚焦各种让人眼花缭乱的查询方式
,认真看,仔细看!本篇的东西真的非常重要!由于查询相关的内容非常多,我们将分为一系列文章来唠叨,各位耐心点儿,心急吃不了热豆腐~
2、准备工作
话说本集的主题是查询数据,所以先得确定一下查哪个表吧,确定了表之后表里头先得有数据吧,要不查个屁呀~ 所以我们先搞定用什么表和为表中填入数据的工作。
用什么表
为简单起见,我们就复用之前在数据库test1
下边创建的学生信息表student_info
和学生成绩表student_score
,你可能有点忘了这两个表长啥样了,我们先把两个表的结构回顾一下:
学生基本信息表的结构
CREATE TABLE student_info (
number INT PRIMARY KEY,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18),
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE,
UNIQUE KEY (id_number)
);
学生成绩表的结构
CREATE TABLE student_score (
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number, subject),
CONSTRAINT FOREIGN KEY(number) REFERENCES student_info(number)
);
为表填入数据
我们给这两个表插入一些数据,先来为student_info
表插入数据:
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140501','田坤','男','1548742154781354','软件学院','计算机科学','2018-01-26');
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140502','绕晶','女','5481645125642189','计算机学院','软件工程','2018-01-26');
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140503','胡浩','男','5478412360125478','软件学院','软件工程','2018-01-26');
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140504','张欢','男','5478412360125479','计算机学院','计算机科学','2018-01-26');
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140505','李俊','男','5478412360125470','软件学院','软件工程','2018-01-26');
insert into `student_info` (`number`, `name`, `sex`, `id_number`, `department`, `major`, `enrollment_time`) values('20140506','胡歌','男','5478412360125471','材料学院','无机非金属','2018-01-26');
再来为student_socre
表插入数据:
insert into `student_score` (`number`, `subject`, `score`) values('20140501','数据结构','100');
insert into `student_score` (`number`, `subject`, `score`) values('20140501','数据结构','100');
insert into `student_score` (`number`, `subject`, `score`) values('20140502','操作系统','78');
insert into `student_score` (`number`, `subject`, `score`) values('20140502','操作系统','78');
insert into `student_score` (`number`, `subject`, `score`) values('20140503','操作系统','98');
insert into `student_score` (`number`, `subject`, `score`) values('20140504','计算机网络','84');
现在这两个表中的数据就如下所示了:
好了,表的填充工作也已经做完了~ 终于可以开始查询数据了!
3、开始查询
3.1 查询单个列
查看某个表中的某一列的数据的通用格式是这样:
SELECT 列名 FROM 表名;
比如查看student_info
表中的number
列的数据可以这么写:
mysql> select number from student_info;
+----------+
| number |
+----------+
| 20140501 |
| 20140502 |
| 20140503 |
| 20140504 |
| 20140505 |
| 20140506 |
+----------+
我们把要查询的东西称为查询对象
,本例中的查询对象就是number
列,因为查询的结果也是由一条一条记录组成的,像记录的集合一样,所以有时候我们会吧得到的查询结果称为结果集
。
小贴士:
你可能发现查询出的数据并不是有序的,这个我们稍后就会说到,稍安勿躁
列的别名
我们也可以为结果集中的列重新定义一个别名
,命令格式如下:
SELECT 列名 [AS] 列的别名 FROM 表名;
我们看到AS
被加了个中括号,意味着可有可无,没有AS
的话,列名和列的别名用空白字符隔开就好了。比如我们想给number
列起个别名,下边这两种方式都可以使用:
-
方式一
SELECT number AS 学号 FROM student_info;
-
方式二:
SELECT number 学号 FROM student_info;
我们执行一下:
mysql> SELECT number AS 学号 FROM student_info;
+----------+
| 学号 |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql>
看到黑框框里显示的列名就不再是number
,而是我们刚刚定义的别名学号
了。不过需要注意的是:列名只是作用在本次查询的显示结果中,而不会改变真实表中的列名,也就是说下一次查询中你对number
列取别的列名也可以,比如这样:
mysql> SELECT number xuehao FROM student_info;
+----------+
| xuehao |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql>
这次输出的列名就是另一个别名xuehao
了。
3.2 查询多个列
如果想查询多个列的数据,可以在SELECT
后边写多个列名,用逗号,
分隔开就好:
SELECT 列名1, 列名2, ... 列名n FROM 表名;
我们把多个查询对象
组成的列表称为查询列表
,需要注意的是,查询列表中的列名可以按任意顺序摆放,结果集将按照我们给出的列名顺序显示。比如我们查询student_info
中的多个列:
select number,name,id_number,major from student_info;
本例中的查询列表就是number,name,id_number,major
,所以结果集中列的顺序就按找这个顺序来显示。当然,我们也可以用别名来输出这些数据:
SELECT number 学号,NAME 姓名,id_number 身份证,major 专业 FROM student_info;
3.3 查询所有列
如果需要把记录中的所有列都查出来,MySQL
也提供一个省事儿的办法,我们之前也介绍过,就是直接用星号*
来表示要查询的东西,就像这样:
SELECT * FROM 表名;
这个命令我们之前看过了,就不多唠叨了。不过需要注意的是,除非你确实需要表中的每个列,否则一般最好别使用星号*
来查询所有列,虽然星号*
看起来很方便,不用明确列出所需的列,但是查询不需要的列通常会降低性能。
3.4 去除相同的查询结果
去除单列的重复结果
有的时候我们查询某个列的数据时会有一些重复的结果,比如我们查询一下student_info
表的学院信息:
SELECT department FROM student_info;
因为表里有6条记录,所以给我们返回了6条结果。但是其实好多都是重复的结果,如果我们想去除重复结果的话,可以使用DISTINCT
放在被查询的列前边,就是这样:
SELECT DISTINCT 列名 FROM 表名;
我们对学院信息做一下去重处理:
看到结果只剩下不重复的信息了。
去除多列的重复结果
对于查询多列的情况,两条记录重复的意思是:两条记录的每一个列中的值都相同。比如查询学院和专业信息:
mysql> select department,major from student_info;
+-----------------+-----------------+
| department | major |
+-----------------+-----------------+
| 软件学院 | 计算机科学 |
| 计算机学院 | 软件工程 |
| 软件学院 | 软件工程 |
| 计算机学院 | 计算机科学 |
| 软件学院 | 软件工程 |
| 材料学院 | 无机非金属 |
| 生物学院 | 生物工程 |
+-----------------+-----------------+
7 rows in set (0.01 sec)
查询结果中第1、2行记录中的department
和major
列都相同,所以这两行记录就是重复的,同理,第3、4行也是重复的。如果我们想对多列查询的结果去重的话,可以直接把DISTINCT
放在被查询的列的最前边:
SELECT DISTINCT 列名1, 列名2, ... 列名n FROM 表名;
比如这样:
mysql> select distinct department,major from student_info;
+-----------------+-----------------+
| department | major |
+-----------------+-----------------+
| 软件学院 | 计算机科学 |
| 计算机学院 | 软件工程 |
| 软件学院 | 软件工程 |
| 计算机学院 | 计算机科学 |
| 材料学院 | 无机非金属 |
| 生物学院 | 生物工程 |
+-----------------+-----------------+
6 rows in set (0.01 sec)
DISTINCT注意事项
DISTINCT
不能做到一部分查询列去重,另一部分不去重。因为查询结果是以行为单位展示的,如果你只对department
去重,那department
那一列只剩下4行数据,对major
列不去重,那major
列剩下了8行数据,那结果应该怎么展示呢?所以我们规定DISTINCT
只能用来对全部列的值都相同的记录来进行去重。
3.5 限制查询结果条数
有时候查询结果的条数会很多,都显示出来可能会撑爆屏幕~ 所以MySQL
给我们提供了一种限制结果条数的方式,就是在查询语句的末尾使用这样的语法:
LIMIT 开始行, 限制条数;
开始行
指的是我们想从第几行数据开始查询,限制条数
是查询结果最多返回的记录条数。
小贴士
在生活中通常都是从1开始计数的,而在计算机中都是从0开始计数的,所以我们平时所说的第1条记录在计算机中算是第0条。比如`student_info`表里的6条记录在计算机中依次表示为:第0条、第1条、第2条、第3条、第4条、第5条。
比如我们查询一下student_info
表,从第0条记录开始,最多查询2条记录可以这么写:
mysql> select * from student_info limit 0,2;
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
| number | name | sex | id_number | department | major | enrollment_time |
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
| 20140501 | 田坤 | 男 | 1548742154781354 | 软件学院 | 计算机科学 | 2018-01-26 |
| 20140502 | 绕晶 | 女 | 5481645125642189 | 计算机学院 | 软件工程 | 2018-01-26 |
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
2 rows in set (0.00 sec)
如果指定的开始行
大于结果中的行数,那查询结果就是什么都没有:
mysql> SELECT number, name, id_number, major FROM student_info LIMIT 6, 2;
Empty set (0.00 sec)
mysql>
如果查询的结果条数小于限制条数
,那就可以全部显式出来:
mysql> select * from student_info limit 4,5;
+----------+--------+------+------------------+--------------+-----------------+-----------------+
| number | name | sex | id_number | department | major | enrollment_time |
+----------+--------+------+------------------+--------------+-----------------+-----------------+
| 20140505 | 李俊 | 男 | 5478412360125470 | 软件学院 | 软件工程 | 2018-01-26 |
| 20140506 | 胡歌 | 男 | 5478412360125471 | 材料学院 | 无机非金属 | 2018-01-26 |
| 20140507 | test | 男 | 5478412360125471 | 生物学院 | 生物工程 | 2018-01-26 |
+----------+--------+------+------------------+--------------+-----------------+-----------------+
3 rows in set (0.00 sec)
从第4条开始的记录有两条,限制条数
为3,所以结果都可以显示出来。
使用默认的开始行
LIMIT
后边也可以只有一个参数,那这个参数就代表着限制行数
。也就是说我们可以不指定开始行
,默认的开始行就是第0行,比如我们可以这么写:
mysql> select * from student_info limit 3;
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
| number | name | sex | id_number | department | major | enrollment_time |
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
| 20140501 | 田坤 | 男 | 1548742154781354 | 软件学院 | 计算机科学 | 2018-01-26 |
| 20140502 | 绕晶 | 女 | 5481645125642189 | 计算机学院 | 软件工程 | 2018-01-26 |
| 20140503 | 胡浩 | 男 | 5478412360125478 | 软件学院 | 软件工程 | 2018-01-26 |
+----------+--------+------+------------------+-----------------+-----------------+-----------------+
3 rows in set (0.01 sec)
查询结果就展示了从第0条开始的3条记录。
3.6 对查询结果排序
我们之前查询number
列的时候得到的记录并不是有序的,这是为什么呢?MySQL
其实默认会按照这些数据底层存储的顺序来给我们返回数据,但是这些数据可能会经过更新或者删除,如果我们不明确指定按照什么顺序来排序返回结果的话,那我们可以认为该结果中记录的顺序是不确定的。换句话说如果我们想让返回结果中的记录按照某种特定的规则排序,那我们必须显式的指定排序规则。
按照单个列的值进行排序
我们可以用下边的语法来指定返回结果的记录按照某一列的值进行排序:
ORDER BY 列名 ASC|DESC
ASC
和DESC
指的是排序方向。ASC
是指按照指定列的值进行由小到大进行排序,也叫做升序
,DESC
是指按照指定列的值进行由大到小进行排序,也叫做降序
,中间的|
表示这两种方式只能选一个。这回我们用student_score
表测试一下:
mysql> select * from student_score order by score desc;
±---------±----------------±------+
| number | subject | score |
±---------±----------------±------+
| 20140501 | 数据结构 | 100 |
| 20140501 | 数据结构 | 100 |
| 20140503 | 操作系统 | 98 |
| 20140504 | 计算机网络 | 84 |
| 20140502 | 操作系统 | 78 |
| 20140502 | 操作系统 | 78 |
±---------±----------------±------+
6 rows in set (0.00 sec)
可以看到输出的记录就是按照成绩由小到大进行排序的。如果省略了 ORDER BY 语句中的排序方向,则默认按照从小到大的顺序进行排序,也就是说ORDER BY 列名
和ORDER BY 列名 ASC
的语义是一样的,我们试一下:
mysql> select * from student_score order by score;
+----------+-----------------+-------+
| number | subject | score |
+----------+-----------------+-------+
| 20140502 | 操作系统 | 78 |
| 20140502 | 操作系统 | 78 |
| 20140504 | 计算机网络 | 84 |
| 20140503 | 操作系统 | 98 |
| 20140501 | 数据结构 | 100 |
| 20140501 | 数据结构 | 100 |
+----------+-----------------+-------+
6 rows in set (0.00 sec)
按照多个列的值进行排序
我们也可以同时指定多个排序的列,多个排序列之间用逗号,
隔开就好了,就是这样:
ORDER BY 列1 ASC|DESC, 列2 ASC|DESC ...
比如我们想让对student_score
的查询结果先按照subjuect
排序,再按照score
值从大到小的顺序进行排列,可以这么写:
mysql> select * from student_score order by subject,score desc;
+----------+-----------------+-------+
| number | subject | score |
+----------+-----------------+-------+
| 20140503 | 操作系统 | 98 |
| 20140502 | 操作系统 | 78 |
| 20140502 | 操作系统 | 78 |
| 20140501 | 数据结构 | 100 |
| 20140501 | 数据结构 | 100 |
| 20140504 | 计算机网络 | 84 |
+----------+-----------------+-------+
6 rows in set (0.00 sec)
再提醒一遍,如果不指定排序方向,则默认使用的是ASC
,也就是从小到大的升序规则。
小贴士:
对于数字的排序还是很好理解的,但是字符串怎么排序呢?大写的A和小写的a哪个大哪个小?这个问题涉及到字符串使用的编码方式以及字符串排序规则,我们之后会详细的介绍它们,现在你只需要知道排序的语法就好了。
我们还可以让ORDER BY
语句和LIMIT
语句结合使用,不过 ORDER BY 语句必须放在 LIMIT 语句前边,比如这样:
mysql> select * from student_score order by score limit 1;
+----------+--------------+-------+
| number | subject | score |
+----------+--------------+-------+
| 20140502 | 操作系统 | 78 |
+----------+--------------+-------+
1 row in set (0.00 sec)
这样就能找出成绩最低的那条记录了。
4、总结
- 我们可以在
SELECT
后边指定要查询的列的列表,然后在FROM
后边指定要查询的表,可以只查询单个列的值,也可以查询多个列的值,也可以使用*
简单的代表查询所有列的值。 - 如果我们想去除重复结果的话,可以使用
DISTINCT
放在被查询的列前边。需要注意的是,两条记录重复的意思是,所以使用DISTINCT
在多个列上会把两条记录的每一个列中的值都相同的重复行去掉,而不能做到不能做到一部分列去重,另一部分不去重。 - 使用
LIMIT
语句限制查询结果的行数,LIMIT
子句可以携带两个参数,其中开始行
指的是我们想从第几行数据开始查询,限制条数
是查询结果最多返回的记录条数。参数开始行
可以被省略,默认从第0行开始。 - 如果我们想让返回结果中的记录按照某种特定的规则排序,那我们必须显式的使用
ORDER BY
指定排序规则。其中,ASC
指按照指定列的值的升序排序,DESC
指按照指定列的值的降序排序。如果ORDER BY
子句后有多个列的话,会先按照前边的列进行排序,如果前边的列的值相同,在相同的这些行中再按照后边的列进行排序。