文章目录
- 1.基本聚集函数
- (1)基本聚集函数的介绍
- (2)使用基本聚集函数的简单例子
- (1)查询最大年龄,最小年龄年龄和平均年龄
- <1>最大年龄
- <2>最小年龄
- <3>平均年龄
- (2)配合上where语句,查询女士的平均年龄
- (3)多个函数的共同使用
- 2.分组聚集
- (1)一个简单的例子
- 统计学生所在城市
- 3.having子句
- (1) where 和 having的区别
- <1>group by + where 的执行流程
- <2>group by + having 的执行
- <3>同时有where、group by 、having的执行顺序
- <4>having子句和where 的区别和联系
- <5>使用group by需要注意的问题
- A.group by不一定要配合聚合函数使用
- B.group by后面的字段也不一定要出现在查询字段中
- C.分组导致的慢Sql问题
- D.分组导致的慢Sql的优化方案
- (a)不排序
- (b)不使用磁盘
- 4.Sql的书写顺序和执行顺序
- 1.书写顺序
- distinct的含义和使用方法
- 作用:
- 使用方法
- 例子
- 2.执行顺序
- 5.CASE语句的两种形式
- (1)简单CASE语句
- (2)搜索CASE语句
- 在查询语句使用CASE
- 在更新语句中使用
- 在 ORDER BY语句中使用
- 6.`CASE` 语句的注意事项
聚集函数是以一组值作为执行的输入,返回单个值函数,聚集函数也被称为组函数。聚集函数通常会和GROUP BY子句和HAVING一同使用的,SQL提供了五个固有聚集函数。
1.基本聚集函数
(1)基本聚集函数的介绍
函数 | 作用 | 语法 |
---|---|---|
avg | 平均值 | SELECT AVG(字段名/列名) FROM 表名 |
min | 最小值 | SELECT MIN(column_name) FROM 表名 |
max | 最大值 | SELECT MAX(字段名/列名) FROM 表名 |
sum | 总和 | SELECT SUM(字段名/列名) FROM 表名 |
count | 计数 | SELECT COUNT(字段名/列名) FROM 表名 |
(2)使用基本聚集函数的简单例子
表结构大概就是这个样子
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',`id_card` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '身份证号码',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',`age` int(4) NOT NULL COMMENT '年龄',`city` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '城市',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '学生表' ROW_FORMAT = Compact;-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '', '小李', 9, '北京');
INSERT INTO `student` VALUES (15, '', '小李', 11, '北京');
INSERT INTO `student` VALUES (16, '', '小李', 23, '北京');
INSERT INTO `student` VALUES (17, '', '小李', 22, '北京');
INSERT INTO `student` VALUES (18, '', '小李', 18, '上海');
INSERT INTO `student` VALUES (19, '', '小李', 47, '上海');
INSERT INTO `student` VALUES (20, '', '小李', 6, '上海');
INSERT INTO `student` VALUES (21, '', '小李', 47, '上海');
INSERT INTO `student` VALUES (22, '', '小李', 16, '魔都');
INSERT INTO `student` VALUES (23, '', '小李', 19, '魔都');
INSERT INTO `student` VALUES (24, '', '小李', 21, '魔都');SET FOREIGN_KEY_CHECKS = 1;
(1)查询最大年龄,最小年龄年龄和平均年龄
<1>最大年龄
select max(age) from student
<2>最小年龄
select min(age) from student
<3>平均年龄
select avg(age) from student
(2)配合上where语句,查询女士的平均年龄
select avg(age) from student WHERE sex = '女'
(3)多个函数的共同使用
iphone表
id | name | Price |
---|---|---|
1 | HuaWei | 6000 |
2 | XiaoMi | 8000 |
3 | Vivo | 600 |
4 | Quant | 9000 |
5 | NUoa | 1200 |
SELECT COUNT(*) AS nums,
MIN(Price) AS min_Price,
MAX(Price) AS max_Price,
AVG(Price) AS avg_Price,
SUM(Price) AS sum_Price
FROM iphone
查询结果
nums | min_Price | max_Price | avg_Price | sum_Price |
---|---|---|---|---|
5 | 600 | 9000 | 4960 | 24800 |
2.分组聚集
group by 子句作用:对给出的一个或多个属性来构造分组,将属性上取值相同的元组(数据库中的每一行就是一个元组)分到同一组中。
(1)一个简单的例子
统计学生所在城市
select city,count(*) as num from student group by city;
还可以在这个基础上加上一个按照性别分组的字段,如下
select sex,city,count(*) as num from student group by city,sex;
3.having子句
(1) where 和 having的区别
<1>group by + where 的执行流程
执行下面的语句
explain select city ,count(*) as num from student where age> 20 group by city;
可以发现查询条件使用了全表扫描,并且使用了临时表和排序
- 创建内存临时表,表里有两个字段
city
和num
; - 全表扫描,找到大于年龄大于20的主键ID,找到city = ‘X’
- 判断临时表中是否有为 city='X’的行,没有就插入一个记录 (X,1);
- 如果临时表中有city='X’的行的行,就将x 这一行的num值加 1;
- 继续重复2步骤,找到所有满足条件的数据,
- 最后根据字段
city
做排序,得到结果集返回给客户端。
<2>group by + having 的执行
查询居住人数大于等于4的城市名
select city ,count(*) as num from student group by city having num >= 4;
having子句被称为分组过滤条件
<3>同时有where、group by 、having的执行顺序
<4>having子句和where 的区别和联系
区别:
- 过滤对象不同
- where后面跟的过滤对象是数据库中已经有的字段名,过滤的对象是行
- having子句后面跟的是聚合函数,过滤的对象是是分组
- 过滤时间不同,在sql语句中书写位置不同
- having是在分组后对数据进行过滤
- where是在分组前对数据进行过滤
- having只能用在group by之后,where执行在group by之前
联系:
两者都是限定条件对数据进行筛选
<5>使用group by需要注意的问题
A.group by不一定要配合聚合函数使用
没错你没看错,group by可以不配合聚合函数使用,这在语法上是没有任何问题的,不过一般配合聚合函数使用才会有具体意义。
下面给一个不配合聚合函数使用的例子:
**注意:**不配合聚合函数使用的话,会返回每个分组中的第一行数据
select city,age from student group by city;
B.group by后面的字段也不一定要出现在查询字段中
是的你没看错,group by后面的字段,在语法中不出现在select后面的字段中也是没问题的
来个例子来帮助理解一下吧
select id from student group by city;
C.分组导致的慢Sql问题
使用group by不当的话其实是容易产生慢SQL的问题的,产生这个问题的原因是因为在执行sql的过程中,用到了临时表和默认的排序,有时候甚至会遇到磁盘临时表。
- 在执行过程中,如果达到临时表的上限后,内存临时表会转成磁盘临时表,速度就会慢下来
D.分组导致的慢Sql的优化方案
- 不使用磁盘临时表
- 不进行排序
(a)不排序
-
给group后面的字段加索引(这样可以保证字段本身就是有序的,自然不需要排序)
-
使用order by null
select city ,count(*) as num from student group by city order by null
(b)不使用磁盘
- 适当调大tmp_table_size参数,这样会扩大内存临时表的容量。
- 使用SQL_BIG_RESULT优化
在数据量过大一定会用到内存临时表时,使用
SQL_BIG_RESULT
这个关键字直接用磁盘临时表
4.Sql的书写顺序和执行顺序
1.书写顺序
SELECT- DISTINCT- FROM- JOIN ON- WHERE- GROUP BY- HIVING- ORDER BY- LIMIT
distinct的含义和使用方法
作用:
distinct用来查询不重复字段值,可以使用"count(distinct city)"来返回不重复字段值的条数,distinct只能返回他的目标字段,而无法返回其他字段。
使用方法
distinct 字段名(如id)
例子
- 对单个字段使用
select distinct city from student
查询结果
city |
---|
北京 |
上海 |
魔都 |
- 对多个字段使用
select distinct age,city from student
查询结果
id | city |
---|---|
9 | 北京 |
11 | 北京 |
22 | 北京 |
18 | 上海 |
47 | 上海 |
6 | 上海 |
16 | 魔都 |
19 | 魔都 |
22 | 魔都 |
2.执行顺序
FROM- ON- JOIN- WHERE- GROUP BY- HAVING- SELECT- DISTINCT- ORDER BY- LIMIT
5.CASE语句的两种形式
CASE
语句是 SQL 的条件判断类似于编程语言中的if-else
语句。- 可以在
SELECT
、UPDATE
、DELETE
等 SQL 语句中使用,以基于不同条件返回不同的值或执行不同的操作。
- 简单
CASE
语句 - 搜索
CASE
语句
(1)简单CASE语句
简单CASE语句是对一个表达式的多个可能值进行比较
举个栗子
SELECT id, weekday,CASE weekdayWHEN '1' THEN '周一'WHEN '2' THEN '周二'WHEN '3' THEN '周三'WHEN '4' THEN '周四'WHEN '5' THEN '周五'ELSE '周末'END AS Weekday
FROM week where id in (1,4,6);
(2)搜索CASE语句
举个栗子:
在查询语句使用CASE
根据年龄来,对各个年龄的女性,称呼
[🐕]
SELECT id, age,CASEWHEN age <= 10 THEN '小妹妹'WHEN age <= 30 THEN '小姐姐'WHEN age >30 THEN '女士'ELSE '未知'END AS cal
FROM student
where sex = '女'
order by age;
在更新语句中使用
进行动态的更新
在一个公司表中,根据销售额动态的确定员工的奖金:
- employees 员工表
- sales_amount 销售额
- bonus 奖金
UPDATE employees
SET bonus = CASEWHEN sales_amount >= 100000 THEN 10000WHEN sales_amount >= 50000 THEN 5000ELSE 1000END
FROM sales
WHERE employees.emp_id = sales.emp_id;
员工按照销售额来动态的设置员工奖金
在 ORDER BY语句中使用
自定义排序
- students 学生表
- age 年龄
- score 分数
SELECT * FROM students
ORDER BY CASE WHEN age < 18 THEN ageWHEN age >= 18 AND score >= 90 THEN scoreELSE nameEND
首先按照年龄进行排序,年龄小于18的学生排在前面;
然后按照成绩进行排序,成绩大于等于90的学生排在前面;
最后按照姓名进行排序。
6.CASE
语句的注意事项
- 数据类型:所有的 result(就是when后面的值) 值必须是同一数据类型或可以隐式转换为同一数据类型。
- NULL 处理:在
CASE
语句中处理NULL
值时,需要特别注意,因为NULL
不等于任何值,包括它自己。可以使用IS NULL
来检查NULL
值。 - 顺序:条件的顺序很重要,因为
CASE
语句会按顺序评估条件,遇到第一个为真的条件时返回相应的结果。