【SQL自学打卡|DAY16】——聚合分组查询

前言

❤欢迎大家阅读我的文章呀❤
今天学习聚合分组查询
希望你们在我的文章当中能有所收获!!!
SLogan:日拱一卒,功不唐捐!

知识点回顾

表的创建、修改与删除

在这里插入图片描述

注意点

自增ID:AUTO_INCREMENT
主键:PRIMARY KEY
唯一性约束:UNIQUE KEY
非空约束:NOT NULL
设置默认值:DEFAULT 0
当前时间戳:CURRENT_TIMESTAMP
评论/注释:COMMENT

修改表:

① 增加列在某列之后
alter table 增加的表格 add 增加列的名称 数据类型 位置(after level 在level 之后)

②更换列的名称及数据类型
alter table user_info change 原列名 修改列名 修改数据类型

③ 更改数据类型
alter table 表名 modify 修改列名称 数据类型 默认值等

索引创建、删除与使用:

在这里插入图片描述

索引创建规则

1、普通索引:
(1)alter table 表名 add index 索引名称(列名);
(2)create index 索引名称 on 表名(列名);
2、唯一索引:
(1)alter table 表名 add unique index 索引名称(列名);
(2)create unique index 索引名称 on 表名(列名);
3、全文索引:
(1)alter table 表名 add fulltext index 索引名称(列名);
(2)create fulltext index 索引名称 on 表名(列名);

一、聚合函数

【SQL自学打卡|DAY16】——聚合分组查询_第1张图片


【SQL123】SQL类别高难度试卷得分的截断平均值
【SQL自学打卡|DAY16】——聚合分组查询_第2张图片

解题思路:
本题相对来说比较繁杂的就是这个计算,去掉最大值和最小值,(总成绩-最大值-最小值)/(成绩个数-2)
然后考虑保留小数位数——1位。用ROUND( ,1)
两张表之间也需要联结,最后筛选的条件就是SQL 和hard。

代码如下:

SELECT tag,difficulty,ROUND((SUM(score)-MAX(score)-MIN(score))/(COUNT(score)-2),1) AS clip_avg_score
FROM exam_record AS B
LEFT JOIN examination_info AS A
ON A.exam_id=B.exam_id
WHERE tag='SQL' AND difficulty='hard'	

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第3张图片

【SQL124】 统计作答次数
【SQL自学打卡|DAY16】——聚合分组查询_第4张图片

解题思路:
本题主要是使用COUNT( )进行计数,需要仔细的点就在于第三列数据,需要同时满足exam_id 和score两列不为空值,还需要将试卷去重,先把大框架写好,再根据题目意思一步一步完善。
代码如下:

SELECT 
    COUNT(exam_id) AS total_pv,
    COUNT(submit_time) AS complete_pv,
    COUNT(DISTINCT exam_id AND score IS NOT NULL) AS complete_exam_cnt
FROM exam_record

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第5张图片

【SQL125】 得分不小于平均分的最低分
【SQL自学打卡|DAY16】——聚合分组查询_第6张图片

解题思路:
本题由题意可知,有以下几个点需要注意:
找到SQL类试卷得分的平均分。
试卷作答记录表需要与试卷信息表相联结
筛选试卷 ‘SQL’
取平均分:avg(score)
找到分数不小于平均分的记录:where tag=‘SQL’ and score>=(…)
取最低分:min(score)
代码如下:

SELECT min(A.score) AS min_score_over_avg
FROM exam_record AS A 
JOIN examination_info AS B
ON A.exam_id = B.exam_id
WHERE B.tag = 'SQL'
AND score >= (select avg(A.score)
             from exam_record AS A
             JOIN examination_info AS B
             ON A.exam_id = B.exam_id
             WHERE tag = 'SQL'
             )

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第7张图片

二、分组查询

【SQL自学打卡|DAY16】——聚合分组查询_第8张图片

【SQL126】平均活跃天数和月活人数
【SQL自学打卡|DAY16】——聚合分组查询_第9张图片
【SQL自学打卡|DAY16】——聚合分组查询_第10张图片

解题思路:
根据提交时间submit_time不为空筛选活跃的的人。知识点:select…from…where…
筛选每个月的平均活跃天数和总活跃人数:
根据月份来选择时间。知识点:date_format() 通过这个函数匹配’%Y%m’年份和月份;

DATE_FORMAT(date,format)
date 参数是合法的日期。format 规定日期/时间的输出格式。

计算用户平均活跃天数:
根据不同的日期且不同的用户ID统计每个月用户的总活跃天数。知识点:distinct、count()、date_format()
统计每个月用的总人数。知识点:distinct、count()
总天数/总人数得到每个月的用户平均活跃天数;
计算每月总活跃人数,直接统计每月不同的用户id数。知识点:count()、distinct
按照月份分组group by date_format(submit_time, ‘%Y%m’) 知识点:group by …
保留两位小数。 知识点:round(x,2)

这道题我反复做了很久,问题出在GROUP BY首先没有想到,其次是平均活跃天数的计算,慢慢排错,根据错误点去修正。
正确代码如下:

SELECT 
    date_format(start_time, '%Y%m' ) AS month,
    ROUND(COUNT(DISTINCT uid,date_format(start_time,'%Y%m%d'))/COUNT(DISTINCT uid),2) AS avg_active_days,
    COUNT(DISTINCT uid) AS mau
FROM exam_record
WHERE submit_time IS NOT NULL AND YEAR(submit_time)=2021 
GROUP BY month

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第11张图片

【SQL127】月总刷题数和日均刷题数
【SQL自学打卡|DAY16】——聚合分组查询_第12张图片

解题思路:
这一题我做了好久,和其他大神的结果比对了好久,这道题非常值得考究,还是需要再琢磨琢磨。
有很多需要注意的细节:
需要用到date_format()函数、count()函数、LAST_DAY()函数、avg()函数、ROUND()函数、year()函数、where条件筛选、group by分组、order by排序其他没有了 因为语句比较简单 就是写的时候比较麻烦 但是就是思路很简单 然后就是只要把这几个函数弄明白怎么用的就可以

date_format()函数:链接日期格式化

LAST_DAY():也是日期函数类 是计算当前月的最后一天

正确代码如下:

select
date_format(submit_time,'%Y%m') as submit_month,
count(submit_time) as month_q_cnt ,
ROUND(count(*) / avg(day(LAST_DAY(submit_time))) ,3)as avg_day_q_cnt
from practice_record
where year(submit_time) = '2021'
group by date_format(submit_time,'%Y%m')
 
 
union all
SELECT
 '2021汇总' as submit_month,
    count( submit_time ) AS month_q_cnt,
    round(
        count( submit_time ) / 31 ,
    3)as avg_day_q_cnt
from practice_record
where year(submit_time) = '2021'
order by submit_month

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第13张图片

【SQL128 难!】未完成试卷数大于1的有效用户
【SQL自学打卡|DAY16】——聚合分组查询_第14张图片
【SQL自学打卡|DAY16】——聚合分组查询_第15张图片

解题思路:

关联作答记录和试卷信息:left join examination_info on using(exam_id);(题中exam_record中的exam_id在examination_info均存在,所以用left join和inner join效果一样)
筛选2021年的记录:where year(start_time)=2021
获取各用户的tag,start_time及未完成标记和已完成标记,如果该作答记录交卷了则已完成标记为1,未完成标记为0,否则相反:if(submit_time is null, 1, null) as incomplete
按用户分组:group by uid
统计未完成试卷作答数和已完成试卷作答数:count(incomplete) as incomplete_cnt
统计作答过的tag集合:
对于每条作答tag,用:连接日期和tag:concat_ws(‘:’, date(start_time), tag)
对于一个人(组内)的多条作答,用;连接去重后的作答记录:group_concat(distinct concat_ws(‘:’, date(start_time), tag) SEPARATOR ‘;’)
筛选未完成试卷作答数大于1的有效用户:having complete_cnt >= 1 and incomplete_cnt BETWEEN 2 and 4
完成试卷作答数至少为1:complete_cnt >= 1
未完成数小于5:incomplete_cnt < 5
未完成试卷作答数大于1:incomplete_cnt > 1

正确代码如下:

SELECT uid, count(incomplete) as incomplete_cnt,
    count(complete) as complete_cnt,
    group_concat(distinct concat_ws(':', date(start_time), tag) SEPARATOR ';') as detail
from (
    SELECT uid, tag, start_time,
        if(submit_time is null, 1, null) as incomplete,
        if(submit_time is null, null, 1) as complete
    from exam_record
    left join examination_info using(exam_id)
    where year(start_time)=2021
) as exam_complete_rec
group by uid
having complete_cnt >= 1 and incomplete_cnt BETWEEN 2 and 4
order by incomplete_cnt DESC

结果:
【SQL自学打卡|DAY16】——聚合分组查询_第16张图片

总结

  今天是【SQL进阶挑战】有关于聚合分组查询的专项练习和分享!难难难 写了好久!明天继续巩固,不能囫囵吞枣!!!
  昨天的知识点要好好回顾呀,不然很容易忘记,提前预祝C站的大家们周末快乐!
  一键三连呀,谢谢!!!
  感谢您宝贵的阅读,关注和点赞噢!❤

你可能感兴趣的:(MySQL数据库学习,sql,数据库)