题解 | 统计复旦用户8月练题情况
统计复旦用户8月练题情况
https://www.nowcoder.com/practice/53235096538a456b9220fce120c062b3
SELECT up.device_id, up.university, count(if(month(date)=8,question_id,null)) as question_cnt, sum(if(result = 'right',1,0)) right_question_cnt FROM user_profile up LEFT JOIN question_practice_detail qpd ON up.device_id = qpd.device_id WHERE university = '复旦大学' GROUP BY up.device_id
解题思路:
题目为复旦大学的每个用户在8月份练习的总题目数和回答正确的题目数情况,对于在8月份没有练习过的用户,答题数结果返回0.
根据这句话,我们先明确需要的数据:
1.总题目树 2.回答正确的题目数
从条件入手:复旦大学,每个用户(练习过,没练习过),8月份
由于sql运行顺序是从from开始,所以我们开始写sql的时候,也从from开始写,把select部分的语句放到最后写
FROM user_profile up
LEFT JOIN question_practice_detail qpd
ON up.device_id = qpd.device_id
【涉及两个表,同时并非数据都有对应(根据device_id 对应,右表缺少部分对应数据),用left join】
写出要求条件:复旦大学,8月份,每个用户(个人认为看到“每个”这两字,就要联系到用group by 进行分组聚合)
WHERE university = '复旦大学'
GROUP BY up.device_id【由于右表字段中不存在对应左表的部分数据(4321),若把月份加入到where语句中将会筛选掉4321,4321在右表的对应字段均是null】
写select部分:条件还剩8月份,用户区分练习过和没练习过
count(if(month(date)=8,question_id,null)) as question_cnt / count(if(month(date)=8,1,null)) as question_cnt 这两个相同效果,那为什么要用question_id呢?若question_id存在重复,可用distinct question_id;而若为1的话则会计算重复值
if函数(判断日期是否是八月,为真的返回question_id/1,为假则返回null),为什么要是null,因为count函数不会对null进行计数,若为0则会对其计数。
sum(if(result = 'right',1,0)) right_question_cnt / count(if(result = 'right',result,null)) as question_cnt 效果相同,不同函数用法
使用sum函数则需要使用1和0 ,因为sum函数是求和(1+1+1),并非计数(统计有多少行)
以上是我的理解思路,希望能够帮助各位更好的理解sql的业务问题。文章中若存在错误的地方还请指正,我也还是个sql新手,以上均为个人理解,仅供参考,欢迎讨论指正