查询 select 可以认为是四个基本操作中使用最为频繁的操作,然而数据量比较大的时候,我们不可能查询所有内容,我们一般会搭配其他语句进行查询:
- 假如要查询某一个字段的内容,可以使用 where
- 假如要查询前几条记录,可以使用 limit
- 假如要让查询结果,按照某种顺序显示,可以使用 order by
但是值得注意的是,当select 和上述三者的任意一个或者多个同时出现时,select 并非优先执行,不同语句之间的执行顺序存在优先级。
优先级的问题可以参考:select 与 where、order by、limit 子句执行优先级比较
目录
1、select
(1) 全列查询
(2) 指定列查询
(3) 查询字段为表达式
(4) 为查询结果起别名(as)
(4) 查询结果去重(distinct)
2、条件语句(where)
(1) 比较运算符
(2) 逻辑运算符
3、结果排序(order by)
(1) 一个字段的排序
(2) 多个字段的排序
4、分页(limit)
5、分组(group by)
(1) 无条件分组
(2) 有条件分组(having)
(3) where 与 having 的区别
1、select
select 是最基本的查询,可以搭配 where、limit、order by 等语句使用,除此之外,查询时支持表达式的运算,select基本语法格式如下:
select
[distinct] {* | 字段名1,字段名2, ...}
from 表名
[where ...]
[order by ...]
[limit ...]
(1) 全列查询
全列查询:查询结果会展示所有字段的内容,可以通过附带条件语句来查询符合条件的记录。
-- 展示exam_result表中的 “ 全部记录 ” 的全部字段内容
select * from exam_result;
-- 展示exam_result表中 “ id=1所在记录 ” 的全部字段内容
select * from exam_result where id=1;
(2) 指定列查询
指定列查询:仅显示指定字段的内容
-- 展示exam_result表中的 “ 全部记录 ” 的全部字段内容
select * from exam_result;
-- 展示exam_result表中 “ id=1所在记录 ” 的全部字段内容
select * from exam_result where id=1;
(3) 查询字段为表达式
查询时,字段支持四则运算,而且允许给表达式起别名
也可以对原本的字段作四则运算
(4) 为查询结果起别名(as)
可以为一个字段起别名,来增强字段的辨识性。语法格式如下:
select 字段名 as 别名 ...
也可以为表达式起别名,详见上面第三点 “ 查询字段为表达式 ”
(4) 查询结果去重(distinct)
语法格式如下:
select distinct 字段名 ... -- 对xx字段的结果进行去重
注意:适合对单一字段查询时的去重,存在多个字段时,去重会失效。
2、条件语句(where)
当记录较多的时候,仅使用 select 无法满足满足需求,因为很多记录是不需要的,比如我们要查看xx班级的学生成绩,我只想知道总分大于90分的同学有哪些,此时就需要滤除一些记录。
使用where 语句时,可以搭配比较运算符(>、<、=)、逻辑运算符(and、or、not)和通配符(%、_)一起使用。
语法格式如下:
select ... where 条件表达式
(1) 比较运算符
常用比较运算符如下:
运算符 | 说明 |
>、>=、<、<= | 大于,大于等于,小于,小于等于 |
=、is null | 等于(非NULL字段的比较) |
<=> | 等于(用于判断字段是否等于NULL) |
!= | 不等于(非NULL字段的比较) |
<>、is not null | 不等于(判断字段是否不等于NULL) |
between A1 and A2 | 判断某个字段的值是否在A1和A2之间(注意是闭区间) |
in (option1, option2 ...) | 判断某个字段的值是否为列表中的某一个 |
like | 模糊匹配。搭配通配符使用,% 表示多个字符,_ 表示一个字符 |
在使用上述运算符时,有几点需要注意:
第一,NULL代表字段为空,不可以直接使用等号运算符比较,因为一个空字段和其他值比较没有意义。比如下面这种写法是错误的。
select * from exam_result where name=null -- 等号运算符不能参与null的比较
第二,通配符理解为占位,比如:
-- 查询所有姓张的学生(“张后面可以有多个字符”)
select * from exam_result where name like "张%"
-- 查询所有的张某(“张”后面只能有一个字符)
select * from exam_result where name like "张_"
- “张%”可以理解为保留“张”后面有多个字符的字段,“张_”可以理解为保留“张”后面只有一个字符的字段
- “%张”可以理解为保留“张”前面有多个字符的字段,“_张”可以理解为保留“张”前面只有一个字符的字段
(2) 逻辑运算符
常用逻辑运算符如下:
运算符 | 说明 |
and | 等价于C语言中的逻辑与(&&) |
or | 等价于C语言中的逻辑或(||) |
not | 等价于C语言中的逻辑取反(!) |
-- 查询所有id为1 / 3 / 5,而且姓张的学生
select * from exam_result where id in (1,3,5) and name like '张%'
3、结果排序(order by)
order by 可以对某一个字段或者多个字段进行排序,默认是升序排序。其实就是根据某一个字段来对整个查询结果进行排序。
- order by asc:升序排序(asc代表ascend)
- order by desc:降序排序(desc代表descend)
语法格式如下:
select ... order by 字段名 [asc | desc]
(1) 一个字段的排序
暂时不考虑条件判断,对所有学生的数学成绩进行排序
(2) 多个字段的排序
order by 可以根据多个字段来对查询结果排序。多个字段排序时,遵循的规则是:
- 先根据字段1比较,如果能比较出大小,那就只使用字段1
- 如果字段1中的比较结果为相等,再根据字段2比较
多个字段排序的语法格式如下:
select ... order by 字段名1, 字段名2, ... [asc | desc]
比如要根据语文成绩和数学成绩来对查询结果进行降序排序。我们会发现当字段 chinese 中不存在两个值相等的情况时,会一直根据chinese比较。
4、分页(limit)
所谓分页其实也可以理解为截取,从某个位置开始,截取 N 条记录。实现方式有两种,语法格式如下:
-- start: 表示起始位置,即要从第几行开始截
-- step: 表示步长,即要截多少条记录
-- 方式一:
select ... limit start, step
-- 方式二:
select ... limit step offset start
比如我们要截取前三条记录,第一种方式的查询结果:
第二种方式的查询结果:
5、分组(group by)
(1) 无条件分组
group by 表示根据某一个字段的内容进行分组,以下面这个表为例:
- 假设根据 department 字段分组,分组的结果:技术部、行政部
- 假设根据 department_id 字段分组,分组的结果:1001、1002
需要注意的是,group by 、where、select的执行顺序依次是:where > group by > select
where针对的是整个表数据的筛选,筛选完以后再分组,可以减少要分组的记录;然后才是 group by 分组;最后是在每一个分组中做查询或者表达式计算处理。
-- 先根据字段1分组,然后在字段1分组的基础上,根据字段2分组
select ... group by 字段1, 字段2 ...
假设我们要计算每个部门的人数,基本思路是根据部门分组,然后使用select在每一个分组中统计人数,统计记录数量使用聚合函数count。
(2) 有条件分组(having)
where只适用于筛选整表记录,并不适合筛选分组记录,如果希望对每一个分组进行筛选,我们可以使用 having。having的优先级在group by 之后,因为针对的是分组以后的记录筛选。所以我们可以得到最终的优先级顺序:where > group by > select > having
group by 与 having 搭配使用的格式如下:
select ... group by 字段1, ... having 每一个分组的筛选条件
(3) where 与 having 的区别
where筛选的是表数据,而having 筛选的是每个的分组数据,两者并不冲突,因为他们的执行优先级不同