文章目录
0. 前置说明
0.1 声明
个人笔记,如有侵权,请及时联系
0.2 参考资料
- 《SQL基础教程(第二版)》
- C语言中文网-mysql教程
0.3 演示表
使用的测验表如下所示,测试基于mysql8.0.x
tb_student表
1. 简单查询
1.1 查询指定列和全部列
查询指定列
-- select 后面如果跟多个字段,需要使用逗号间隔
select id, name, age from tb_student;
查询全部列
-- 可以通过 * 代表全部列, 也可以显式的指定每一列
-- 使用 * 号 无法指定显示列的顺序, 同时检索多余的数据,对性能有损耗
select * from tb_student;
select id, name, age, gender, height, course_id from tb_student;
1.2 别名设置
别名设置支持列别名和表别名,通过as关键字设置(AS关键字可以省略,省略后需要将字段名和别名用空格隔开,不建议省略)。
设置别名时应当注意:
- 表的别名不能与该数据库的其它表同名。字段的别名不能与该表的其它字段同名;
- 别名可以设置中文,设置中文时需要引号包裹;
- 在条件表达式中不能使用字段的别名, 因为where优先于select执行, 而表别名可以在select子句中被用来使用;
- 表别名只在执行查询时使用,并不在返回结果中显示。而字段定义别名之后,会返回给客户端显示,显示的字段为字段的别名。
1.2.1 列别名
-- 列别名
select id as '学号', name as '学生姓名', age from tb_student;
1.2.2 表别名
在进行复杂查询的时候,多条语句混合,或者多条查询时,涉及到多个表的引用,需要为表设置别名方便,sql语句中引用这些表, 增加sql可读性。
-- 表别名
-- 表名(或者表别名).列名的方式,叫做完全限定列名
select s.id as '学号', name as '学生姓名', s.age from tb_student as s;
1.3 结果去重
DISTINCT
关键字的主要作用就是对数据表中一个或多个字段重复的数据进行过滤,只返回其中的一条数据给用户。
使用 DISTINCT
的注意事项
- DISTINCT 关键字只能在 SELECT 语句中使用;
- 在对一个或多个字段去重时,DISTINCT 关键字必须在所有字段的最前面;
- DISTINCT关键字应用于所有列而不仅是前置它的列, 如果 DISTINCT 关键字后有多个字段,则会对多个字段进行组合去重,也就是说,只有多个字段组合起来完全是一样的情况下才会被去重;
- 在使用 DISTINCT 时, NULL 也被视为一类数据;
SELECT DISTINCT <字段名> FROM <表名>;
-- 经常使用的场景是 在聚合函数中统计分类
select count(distinct gender) from tb_student;
1.4 结果限制
MySQL中通过LIMIT关键字对结果集进行限制,limit中行数的计算是从0开始的, 行数不够的时候,只显示存在的数据。
1.4.1 Top-N查询(limit)
查询前多少条数据
-- sql 标准
-- fetch first N rows only;
-- mysql实现方式
-- limit
-- 相当于 0 ~ 2 显示3行 即显示前三行数据
select * from tb_student LIMIT 3;
1.4.2 分页查询
通过增加偏移量,实现分页
-- sql 标准 offset M rows fetch first N rows only;
-- mysql实现方式
-- limit
-- 相当于 从第2行开始,显示2行,即展示2,3行的数据
select * from tb_student LIMIT 1, 2;
-- 相当于LIMIT 1, 2
select * from tb_student LIMIT 2 OFFSET 1;
1.5 结果排序
对检出的结果进行排序,需要使用ORDER BY
子句,该子句中所指定的列名被称为排序键。
排序应该注意的事项
- 排序键可以是单列,也可以是多列,多列排序是通过逐一比对进行,如第一列相同,则按第二列进行比较,以此类推;
- 不针对包含NULL值的进行比较, 统一将包含NULL的列汇总到结果的开头 ,或者结尾;
ORDER BY
子句应该在SELECT
语句末尾, 而LIMIT
应该位于ORDER BY
子句之后;- 默认升序即ASC,不需要在ORDER BY中显式的声明, 如果需要使用降序排列,可以在ORDER BY中显示的声明DESC, 如果想在多个列上进行降序排序,必须对每个列指定DESC关键字。
-- 每个列默认都是以升序进行排列的即asc, 改变排序方式需要每个列都更改
select name, height, age from tb_student order by height asc, age desc;
2. 条件查询
在SQL中需要有条件的对数据进行查询,可以通过where子句进行条件指定。
查询条件中支持
- 比较运算符
- 逻辑运算符
- LIKE进行模糊匹配
- IN 和 between … and … 范围匹配
- is null 针对null的判断
2.1 简单条件查询
-- 查询身高为170的同学信息
select * from tb_student where height = 170;
-- 查询身高不为170的同学信息 <> | !=
select * from tb_student where height <> 170;
-- 查询年龄在15到20的同学信息,包括边界值 15和20
select * from tb_student where age between 15 and 20;
select * from tb_student where age >=15 and age <= 20;
-- 查询年龄是15, 20 或者 23的同学信息
select * from tb_student where age in (15, 20, 23);
select * from tb_student where age = 15 or age = 20 or age = 23;
2.2 模糊匹配
通过LIKE关键字来搜索指定内容。
使用like应注意的事项
- 匹配的字符串需要包含在引号内;
- like不区分大小写,针对匹配的结果,需要加binary限定,
like binary
; - 匹配检索比较慢,尽量不要使用。
2.2.1 通配符
%
和_
分别代表任意个(也包括零个)和单个, 两种通配符都无法针对NULL进行匹配。
-- 检索王姓同学
select * from tb_student where name like '王%';
-- 检索姓名中包含宝的同学信息
select * from tb_student where name like '%宝%';
-- 检索两个字名字的同学信息
select * from tb_student where name like '__';
2.2.2 转义
-- 转义
select * from tb_student where name like "ad#_vp" escape "#";
-- 或者直接使用\
select * from tb_student where name like "ad\_vp";
2.2.3 正则表达式
使用正则表达式可以匹配文本中特殊的串。WHERE子句对正则表达式提供了初步的支持。
-- regexp匹配列值 like匹配列 "^aaa" 相当于 “aaa”
select * where name regexp "正则表达式"
-- 添加 binary 已启用匹配时启用大小区分
select * where name regexp binary "正则表达式"
2.3 空值判断
-- 针对null需要使用特殊的判断,不能使用逻辑判断
-- is null
-- is not null
select * from tb_student where name is null;
2.3 复杂条件
通过逻辑运算符组成多条件的查询,逻辑运算符主要包括
- and
- or
- not
WHERE可以包含任意数目的AND和OR运算符,使用时应注意,AND的执行次序高于OR,必要时可以使用圆括号,对条件进行明确分组。not用来表否定,主要是放在条件之前。
-- 查询身高不为170的同学信息
select * from tb_student where not height = 170;
select * from tb_student where age not in (15, 20, 23);
3. 聚合函数
3.1 聚合函数的概念
用于汇总的函数称为聚合函数或者聚集函数。所谓聚合,就是将多行汇总为一行, 即输入多行输出一行。
3.2 聚合函数的注意事项
- 聚合函数会将 NULL 排除在外。但 COUNT (*) 例外,并不会排除 NULL;
- 聚合函数在使用的时候已经将NULL排除在外,不会像四则运算那样,得出NULL结果,count(*)除外;
- 所有的聚合函数都可以使用 DISTINCT, 在聚合函数的参数中使用 DISTINCT, 可以删除重复数据;
- where子句中不能使用聚合函数, 只有having子句,select子句,order by子句中可以使用聚合。
使用聚合函数时, SELECT 子句中只能存在以下三种元素。
- 常数
- 聚合函数
- GROUP BY 子句中指定的列名(也就是聚合键)
3.3 常见的聚合函数
- count函数
- 统计行的数量
- 将包含 NULL 的列作为参数时, COUNT (*) 和 COUNT (<列名>)的结果并不相同
- 其他函数并不能将星号作为参数
- sum函数
- 行数据求和
- avg函数
- 行数据求平均
- max函数
- 行数据求最大值
- min函数
- 行数据求最小值
4. 分组查询
4.1 分组查询的概念
SQL中可以根据一个或多个字段对查询结果进行分组,通过group by关键字实现
分组通常与聚合函数一起使用,进行数据的汇总,如果不使用汇聚函数,可以使用distinct关键字,对数据进行去重,更直观,可读。
-- 统计班级中,男女人数
select gender,count(id) from tb_student group by gender;
-- 如果只是想知道男女的分类,可以直接使用 distinct
select distinct gender from tb_student group by gender;
4.2 分组查询的定义位置
-- 书写顺序
SELECT → FROM → WHERE → GROUP BY
-- 执行顺序
FROM → WHERE → GROUP BY → SELECT
4.3 分组查询的注意事项
- 在
GROUP BY
子句中指定的列称为聚合键或者分组列, 当聚合键中包含NULL
时,也会将NULL
作为一组特定的数据; - 当使用
GROUP BY
进行分组的时候,select子句中的列只能由以下成分组成, 否则会引起报错- 常数
- 聚合函数
- GROUP BY 子句中指定的列名(即聚合键)
- 因为
GROUP BY
的执行顺序高于SELECT
所以,在GROUP BY
中并不能使用列的别名。
如果需要显示分组中该分组下的某些列包含的具体指,可以使用函数GROUP_CONCAT() 演示如下
select GROUP_CONCAT(name), gender from tb_student group by gender;
4.3 对分组进行过滤
分组时可以使用having子句进行分组过滤,因为group by子句在where子句之后执行,同时having中可以使用聚合函数,可以对组进行更加精确的筛选,所以不使用where对分组进行过滤。
-- 书写顺序
SELECT → FROM → WHERE → GROUP BY → HAVING
-- 执行顺序
FROM → WHERE → GROUP BY → HAVING → SELECT
having中条件,只能使用,常数,聚合函数,或者聚合键组合,不能出现其他列。一般将包含聚合键的条件放在where子句中,性能更佳。