现有一张题目练习记录表practice_record,示例内容如下:
id | uid | question_id | submit_time | score |
1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 |
2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 |
3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 |
4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 |
5 | 1003 | 8002 | 2021-08-01 19:38:01 | 80 |
SELECT
coalesce(DATE_FORMAT(submit_time,"%Y%m"),'2021汇总') submit_month,
COUNT(submit_time) month_q_cnt,
round(COUNT(submit_time) / MAX(DAY(last_day(submit_time))),3)avg_day_q_cnt
FROM
practice_record
WHERE
year(submit_time) = '2021'
GROUP BY
DATE_FORMAT(submit_time,"%Y%m") WITH ROLLUP;
开始的想法
开始就想着先算出来然后最后一行用union加上
就遇到了个问题:
计算平均
这里开始我的想法就是计算这个月与下个月之间的日期差datediff然后发现没办法用,要求两个都是date类型,怎么把下个月表示出来是个问题,除非两次转换,所以就放弃了
last_day()
然后看到一个神奇的函数就是last_day()返回参数日期的最后一天那再用day不就能获取这个月的天数了嘛
也就是day(last_day(subnit_time))
select
DATE_FORMAT(submit_time,'%Y%m') as submit_month,
count(*) as month_q_cnt,
round(count(*) / day(last_day(submit_time)) ,3) as avg_day_q_cnt
from practice_record
and year(submit_time) = '2021'
group by DATE_FORMAT(submit_time,'%Y%m')
union all
select
'2021汇总' as submit_month,
count(*) as month_q_cnt,
round(count(*) /31 ,3) as avg_day_q_cnt -- /30 会不通过用例
from practice_record where score is not null
and year(submit_time) = '2021'
order by submit_month ;
再然后就做好了嘛,就看看题解,发现了这两个东西
SELECT
coalesce(DATE_FORMAT(submit_time,"%Y%m"),'2021汇总') submit_month,
COUNT(submit_time) month_q_cnt,
round(COUNT(submit_time) / MAX(DAY(last_day(submit_time))),3)avg_day_q_cnt
FROM
practice_record
WHERE
year(submit_time) = '2021'
GROUP BY
DATE_FORMAT(submit_time,"%Y%m") WITH ROLLUP;
新知识时间
coalesce
COALESCE是一个函数,coalesce (expression_1, expression_2, ...,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值。
SQL实例
1
select coalesce(success_cnt, 1) from tableA
当success_cnt 为null值的时候,将返回1,否则将返回success_cnt的真实值。
1
select coalesce(success_cnt,period,1) from tableA
当success_cnt不为null,那么无论period是否为null,都将返回success_cnt的真实值(因为success_cnt是第一个参数),当success_cnt为null,而period不为null的时候,返回period的真实值。只有当success_cnt和period均为null的时候,将返回1。
在这里题解用的是第一种,也就是当submit_time为null的时候返回一个‘2021汇总’加到最后 那最后的均值呢?
with rollup
with在sql语句中定义在group by之后。当需要对数据库数据进行分类统计的时候,往往会用上groupby进行分组。而在groupby后面还可以加入withcube和withrollup等关键字对数据进行汇总。不过这个cube在mysql中并不适用。
使用 WITH ROLLUP,此函数是对聚合函数进行求和,注意 with rollup是对 group by 后的第一个字段,进行分组计算。
题目应该也是想让用这个函数因为题上给的最后平均就是总数/31而不是一年的365 or366
所以使用这个函数刚好可以
请从中统计出2021年每个月里用户的月总刷题数month_q_cnt 和日均刷题数avg_day_q_cnt(按月份升序排序)以及该年的总体情况,示例数据输出如下:
submit_month | month_q_cnt | avg_day_q_cnt |
202108 | 2 | 0.065 |
202109 | 3 | 0.100 |
2021汇总 | 5 | 0.161 |