排序和分组
排序使用函数 order by默认是升序(ASC),可以使用order by DESC(降序)排列
group by 列名,通过列名分组。
HAVING子句用于在应用GROUP BY子句之后筛选分组的结果。
它通常包含聚合函数,因为筛选条件是基于分组后的统计数据。
HAVING子句不能单独使用,必须与GROUP BY子句一起使用。
WHERE与HAVING的区别:
WHERE子句在分组之前对数据进行筛选,而HAVING子句在数据分组之后进行筛选。
WHERE子句不能包含聚合函数,而HAVING子句可以并且常常包含聚合函数。
当查询中同时包含WHERE、GROUP BY和HAVING子句时,首先执行WHERE子句来过滤记录,然后执行GROUP BY子句进行分组,最后执行HAVING子句来筛选分组后的结果
力扣1045:添加链接描述
思路
题目中给出两个表一个用户id跟买的产品id,另一个表是产品id,要求是我们筛选出买了所有产品的用户id,我一开始的想法是现在产品表中统计出所有的产品数量,然后在第二个表中统计出用户买的数量然后相等可以得出,但是没有地方能让这两个表通过聚合函数查询出来的值判断是否相等,在我看了别人题解后恍然大悟,可以在Having子句中对我们group by分组后的进行筛选,在这里可以使用子查询然后判断
select customer_id
from customer
group by customer_id
having count(distinct(product_key) ) = (select count(*) from Product)
聚合函数
聚合函数包括:AVG(),SUM(),COUNT(),MAX(),MIN()
力扣1211:力扣1211
思路
题目中需要求平均值个和一个比值,其中第一个平均值比较好计算,我们通过group by 分组后计算他的平均值,但是需要保留两位小数,我么通过round(number,小数位数)来处理;求的第三列是一个占比的问题,一开始我想通过先查出<3的求出来单独做一个表,然后链接去做,但是不能达到效果,查看题解后发现了解决办法,题解中提供了SUM(if(rating<3,1,0)),他在聚合函数SUM中写了一个条件表达式:
if(rating<3,1,0):这是一个条件表达式,当 rating 小于 3 时,返回 1,否则返回 0,通过这个我们得到了<3的数量,然后与count(*)做比值即可;同时还出现了一个错误,就是使用group by分组时没有去判断空值的情况也会导致出错,使用 having query_name is not null去除空值的情况
select q1.query_name ,
round(avg(rating/position),2)as quality,
round(sum(if(rating<3,1,0))/count(rating)*100,2)
as poor_query_percentage
from Queries as q1
group by q1.query_name
having query_name is not null;
之后我又发现了另一只求第三列的方法使用avg(rating<3)当<3的时候返回一个1,最后求平均值时除以总的数量
select q1.query_name ,round(avg(rating/position),2)as quality,
round(avg(rating<3)*100,2)as poor_query_percentage
from Queries as q1
group by q1.query_name
having query_name is not null;
总结:
- 使用聚合函数时可以在聚合函数中添加条件语句来进行筛选达到所想的效果,同一个结果可以有不同的方式得到。
- 使用round(number,3)来控制小数点的位数
- 聚合函数中IF(rating>3,1,0)的含义时>3的时候返回1,否则返回0
索引
数据库中索引是一种可以加快查询的数据结构,一般主键是索引也可以自己添加索引:
alter table 表名
add index index_name(列名)
唯一索引(数据不重复)
alter table xxx
add unique index index_name(列名)
索引是允许存在重复的,但是数据重复率越低,索引的效率越高
一个表中索引不是越多越好,因为当我们在增删改的时候会去维护索引,索引太多会增大系统资源开支。