一、SELECT介绍
1.1 SELECT
SELECT
是数据库四大基本操作的一种,用于查询表中的数据信息。
基本的查询语法为:SELECT 列1, 列2, ... FROM 表
,表示从表中取出对应的列。
SELECT
语句的用法多种多样,并且还有很多高级的操作(如排序、分组以及联合等等),是增删改查四种基本操作中用法最多也运用最广的命令。
1.2 测试数据
创建测试表stu_info
,所有的测试将会在这张表上进行:
1 2 3 4 5 6 7 8 |
CREATE TABLE `stu_info` ( `stu_id` int(12) unsigned zerofill NOT NULL AUTO_INCREMENT, `stu_name` varchar(255) NOT NULL DEFAULT '', `age` tinyint(4) NOT NULL, `classno` tinyint(4) NOT NULL, `city` varchar(255) NOT NULL, PRIMARY KEY (`stu_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
表中数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+--------------+-----------+-----+---------+----------+ | stu_id | stu_name | age | classno | city | +--------------+-----------+-----+---------+----------+ | 000000000001 | maqian | 24 | 1 | changsha | | 000000000002 | xiaoming | 19 | 2 | shanghai | | 000000000003 | xiaohua | 23 | 2 | shenzhen | | 000000000004 | xiaobai | 22 | 3 | shenzhen | | 000000000005 | xiaowang | 19 | 4 | hunan | | 000000000006 | xiaozhou | 20 | 3 | wuhan | | 000000000007 | xiaoli | 20 | 1 | changsha | | 000000000008 | xiaopeng | 23 | 1 | changsha | | 000000000009 | xiaozheng | 22 | 1 | fujian | +--------------+-----------+-----+---------+----------+ |
二、使用SELECT查询数据
2.1 查询单列数据
查询所有的学生名字:
1 |
SELECT stu_name FROM stu_info; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-----------+ | stu_name | +-----------+ | maqian | | xiaoming | | xiaohua | | xiaobai | | xiaowang | | xiaozhou | | xiaoli | | xiaopeng | | xiaozheng | +-----------+ |
注意事项:查询时,如果没有明确指定排序对象,返回的数据中顺序没有特殊意义,每次返回的顺序可能都不同。只要保证每次返回的行数是一样的就是正常。
2.2 查询多个列
查询所有学生的名字及年龄信息,查询多列时,不同列之间使用,
隔开:
1 |
SELECT stu_name, age FROM stu_info; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-----------+-----+ | stu_name | age | +-----------+-----+ | maqian | 24 | | xiaoming | 19 | | xiaohua | 23 | | xiaobai | 22 | | xiaowang | 19 | | xiaozhou | 20 | | xiaoli | 20 | | xiaopeng | 23 | | xiaozheng | 22 | +-----------+-----+ |
2.3 查询所有列
使用通配符*
表示查询所有列:
1 |
SELECT * FROM stu_info; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+--------------+-----------+-----+---------+----------+ | stu_id | stu_name | age | classno | city | +--------------+-----------+-----+---------+----------+ | 000000000001 | maqian | 24 | 1 | changsha | | 000000000002 | xiaoming | 19 | 2 | shanghai | | 000000000003 | xiaohua | 23 | 2 | shenzhen | | 000000000004 | xiaobai | 22 | 3 | shenzhen | | 000000000005 | xiaowang | 19 | 4 | hunan | | 000000000006 | xiaozhou | 20 | 3 | wuhan | | 000000000007 | xiaoli | 20 | 1 | changsha | | 000000000008 | xiaopeng | 23 | 1 | changsha | | 000000000009 | xiaozheng | 22 | 1 | fujian | +--------------+-----------+-----+---------+----------+ |
使用
*
来输出所有列时,会严重降低检索和应用程序的性能。大部分时候,尽量少使用用通配符,明确自己所需要的列。
2.4 去除重复数据
在查询时,可以通过DISTINCT
关键字来剔除重复的行。如查询所有的班级(不重复):
1 |
SELECT DISTINCT classno FROM stu_info; |
结果:
1 2 3 4 5 6 7 8 |
+---------+ | classno | +---------+ | 1 | | 2 | | 3 | | 4 | +---------+ |
当对多个关键字使用DISTINCT
时,只有所有列都相同才会被认为是重复的,其中某个字段相同并不会认为是同一个行:
1 |
SELECT DISTINCT classno, city FROM stu_info; |
上面的数据中,有多个classno=1
并且city=changsha
的结果,使用DISTINCT
之后,这些重复的行被剔除了,而同样classno=
但是city=fujian
的记录却依然存在:
1 2 3 4 5 6 7 8 9 10 11 |
+---------+----------+ | classno | city | +---------+----------+ | 1 | changsha | | 2 | shanghai | | 2 | shenzhen | | 3 | shenzhen | | 4 | hunan | | 3 | wuhan | | 1 | fujian | +---------+----------+ |
2.5 限制结果
使用LIMIT
关键字可以限制输出的结果数量,语法格式为:
LIMIT N
:只输出前面N条记录。LIMIT M,N
:从第M条记录开始,输出N条记录。LIMIT N OFFSET M
:MYSQL从5.0开始支持的语法,作用和第二条一样,从M
开始输出N
条记录。
第三种用法实际上是为了解决用户会混淆
M,N
究竟是从M
开始的N
条记录还是N
开始的M
条记录的问题。
2.5.1 显示前面5条记录
1 |
SELECT classno, city FROM stu_info LIMIT 5; |
结果:
1 2 3 4 5 6 7 8 9 |
+---------+----------+ | classno | city | +---------+----------+ | 1 | changsha | | 2 | shanghai | | 2 | shenzhen | | 3 | shenzhen | | 4 | hunan | +---------+----------+ |
2.5.2 从第5条之后显示5条记录
1 |
SELECT classno, city FROM stu_info LIMIT 5, 5; |
结果:
1 2 3 4 5 6 7 8 |
+---------+----------+ | classno | city | +---------+----------+ | 3 | wuhan | | 1 | changsha | | 1 | changsha | | 1 | fujian | +---------+----------+ |
当实际的记录数量小于剩余记录时,输出的结果并不会达到我们想要的行数。
使用
SELECT classno, city from stu_info LIMIT 4 OFFSET 5
的结果也和上面一样!
三、对结果排序
排序是查询是最常用的的功能之一,语法格式为ORDER BY col1, col2
,表示根据col1
和col2
排序。
MYSQL支持对单行和多行数据排序,也支持正序和倒序排序。默认情况是正序排序,逆序排序需要手动添加关键字DESC
。
3.1 对单列数据排序
输出学生的年龄、班级和名字,并针对年龄排序:
1 |
SELECT age, stu_name FROM stu_info ORDER BY age; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-----+---------+-----------+ | age | classno | stu_name | +-----+---------+-----------+ | 19 | 2 | xiaoming | | 19 | 4 | xiaowang | | 20 | 3 | xiaozhou | | 20 | 1 | xiaoli | | 22 | 3 | xiaobai | | 22 | 1 | xiaozheng | | 23 | 2 | xiaohua | | 23 | 1 | xiaopeng | | 24 | 1 | maqian | +-----+---------+-----------+ |
可以看到,age
列都是从小到大排列,而classno
还是处于无序的状态。
3.2 对多列数据排序
在上面的基础上,添加对班级排序逻辑。即当学生年龄一致的时候,根据所在的班级排序:
1 |
SELECT age, classno, stu_name FROM stu_info ORDER BY age, classno; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-----+---------+-----------+ | age | classno | stu_name | +-----+---------+-----------+ | 19 | 2 | xiaoming | | 19 | 4 | xiaowang | | 20 | 1 | xiaoli | | 20 | 3 | xiaozhou | | 22 | 1 | xiaozheng | | 22 | 3 | xiaobai | | 23 | 1 | xiaopeng | | 23 | 2 | xiaohua | | 24 | 1 | maqian | +-----+---------+-----------+ |
结果中,所有年龄相同的行,班级序号也是有序的。
3.3 逆序排序
逆序输出所有的学生名字:
1 |
SELECT stu_name FROM stu_info ORDER BY stu_name DESC; |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
+-----------+ | stu_name | +-----------+ | xiaozhou | | xiaozheng | | xiaowang | | xiaopeng | | xiaoming | | xiaoli | | xiaohua | | xiaobai | | maqian | +-----------+ |
四、其他
4.1 使用完全限定的表名
查询时,可以明确查询的表名和列名,如:
1 |
SELECT stu_info.stu_name from stu_info; |
注意:不可省略最后的表信息,不要认为列中限定了表名最后就不用再添加表名了。
效果等同于:
1 |
SELECT stu_name FROM stu_info; |
这种用法一般适用于多表之间的联合查询,当两个表中的字段有重合时,需要明确指定表名来限定查询的是哪个表中的字段。
评论