这是我参与「第五届青训营 」笔记创作活动的第11天
人生没有白走的路,每一步它都算数——考研政治老师孔昱力
本文就是记录本人在练习sql过程中曾经卡壳的点。
查询结果限制返回行数
题目:现在运营只需要查看前2个用户明细设备ID数据,请你从用户信息表 user_profile 中取出相应结果。
示例:
| id | device_id | gender | age | university | province |
|---|---|---|---|---|---|
| 1 | 2138 | male | 21 | 北京大学 | Beijing |
| 2 | 3214 | male | 复旦大学 | Shanghai | |
| 3 | 6543 | female | 20 | 北京大学 | Beijing |
| 4 | 2315 | female | 23 | 浙江大学 | ZheJiang |
| 5 | 5432 | male | 25 | 山东大学 | Shandong |
根据输入,你的查询应返回以下结果:
| device_id |
|---|
| 2138 |
| 3214 |
select device_id from user_profile limit 0,2---运行效率更高
select device_id from user_profile limit 2 ---运行效率低
也可结合 limit offset: 一起使用时,limit表示要取的数量,offset表示跳过的数量
select device_id from user_profile limit 2 offset 0 // 跳过0条,从第一条数据开始取,取两条数据 ---运行效率中
select
device_id
from
user_profile
order by
id
limit
0, 2
分组计算练习题
题目:现在运营想要对每个学校不同性别的用户活跃情况和发帖数量进行分析,请分别计算出每个学校每种性别的用户数、30天内平均活跃天数和平均发帖数量。
用户信息表:user_profile
30天内活跃天数字段(active_days_within_30)
发帖数量字段(question_cnt)
回答数量字段(answer_cnt)
| id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
|---|---|---|---|---|---|---|---|---|
| 1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
| 2 | 3214 | male | 复旦大学 | 4.0 | 15 | 5 | 25 | |
| 3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
| 4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
| 5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
| 6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
| 7 | 4321 | male | 26 | 复旦大学 | 3.6 | 9 | 6 | 52 |
第一行表示:id为1的用户的常用信息为使用的设备id为2138,性别为男,年龄21岁,北京大学,gpa为3.4在过去的30天里面活跃了7天,发帖数量为2,回答数量为12
。。。
最后一行表示:id为7的用户的常用信息为使用的设备id为4321,性别为男,年龄26岁,复旦大学,gpa为3.6在过去的30天里面活跃了9天,发帖数量为6,回答数量为52
你的查询返回结果需要对性别和学校分组,示例如下,结果保留1位小数,1位小数之后的四舍五入:
| gender | university | user_num | avg_active_day | avg_question_cnt |
|---|---|---|---|---|
| male | 北京大学 | 1 | 7.0 | 2.0 |
| male | 复旦大学 | 2 | 12.0 | 5.5 |
| female | 北京大学 | 1 | 12.0 | 3.0 |
| female | 浙江大学 | 1 | 5.0 | 1.0 |
| male | 山东大学 | 2 | 17.5 | 11.0 |
解释:
第一行表示:北京大学的男性用户个数为1,平均活跃天数为7天,平均发帖量为2
最后一行表示:山东大学的男性用户个数为2,平均活跃天数为17.5天,平均发帖量为11
这个题记录的是求平均值不要在傻傻的自己计算和,然后除总数了。总是忘记有函数
select
gender,
university,
count(gender) user_num,
avg(active_days_within_30) avg_active_day,
avg(question_cnt) avg_question_cnt
from user_profile
group by gender, university
分组过滤练习题
题目:现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营,请取出平均发贴数低于5的学校或平均回帖数小于20的学校。
示例:user_profile
| id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
|---|---|---|---|---|---|---|---|---|
| 1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
| 2 | 3214 | male | 复旦大学 | 4.0 | 15 | 5 | 25 | |
| 3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
| 4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
| 5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
| 6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
| 7 | 4321 | female | 26 | 复旦大学 | 3.6 | 9 | 6 | 52 |
第一行表示:id为1的用户的常用信息为使用的设备id为2138,性别为男,年龄21岁,北京大学,gpa为3.4在过去的30天里面活跃了7天,发帖数量为2,回答数量为12 。。。 最后一行表示:id为7的用户的常用信息为使用的设备id为4321,性别为男,年龄26岁,复旦大学,gpa为3.6在过去的30天里面活跃了9天,发帖数量为6,回答数量为52
根据示例,你的查询应返回以下结果,请你保留3位小数(系统后台也会自动校正),3位之后四舍五入:
| university | avg_question_cnt | avg_answer_cnt |
|---|---|---|
| 北京大学 | 2.5000 | 21.000 |
| 浙江大学 | 1.000 | 2.000 |
解释: 平均发贴数低于5的学校或平均回帖数小于20的学校有2个
属于北京大学的用户的平均发帖量为2.500,平均回答数量为21.000
属于浙江大学的用户的平均发帖量为1.000,平均回答数量为2.000
需要记住的是,分组之后的条件写在having中,where后不能使用聚合函数
select
university,
avg(question_cnt) avg_question_cnt,
avg(answer_cnt) avg_answer_cnt
from user_profile
group by university
having avg(question_cnt)<5 or avg(answer_cnt)<20
统计每个学校的答过题的用户的平均答题数
运营想要了解每个学校答过题的用户平均答题数量情况,请你取出数据。
用户信息表 user_profile,其中device_id指终端编号(认为每个用户有唯一的一个终端),gender指性别,age指年龄,university指用户所在的学校,gpa是该用户平均学分绩点,active_days_within_30是30天内的活跃天数。
| device_id | gender | age | university | gpa | active_days_within_30 |
|---|---|---|---|---|---|
| 2138 | male | 21 | 北京大学 | 3.4 | 7 |
| 3214 | male | NULL | 复旦大学 | 4 | 15 |
| 6543 | female | 20 | 北京大学 | 3.2 | 12 |
| 2315 | female | 23 | 浙江大学 | 3.6 | 5 |
| 5432 | male | 25 | 山东大学 | 3.8 | 20 |
| 2131 | male | 28 | 山东大学 | 3.3 | 15 |
| 4321 | male | 28 | 复旦大学 | 3.6 | 9 |
第一行表示:用户的常用信息为使用的设备id为2138,性别为男,年龄21岁,北京大学,gpa为3.4,在过去的30天里面活跃了7天
最后一行表示:用户的常用信息为使用的设备id为4321,性别为男,年龄28岁,复旦大学,gpa为3.6,在过去的30天里面活跃了9天
答题情况明细表 question_practice_detail,其中question_id是题目编号,result是答题结果。
| device_id | question_id | result |
|---|---|---|
| 2138 | 111 | wrong |
| 3214 | 112 | wrong |
| 3214 | 113 | wrong |
| 6543 | 111 | right |
| 2315 | 115 | right |
| 2315 | 116 | right |
| 2315 | 117 | wrong |
| 5432 | 118 | wrong |
| 5432 | 112 | wrong |
| 2131 | 114 | right |
| 5432 | 113 | wrong |
第一行表示用户的常用信息为使用的设备id为2138,在question_id为111的题目上,回答错误
....
最后一行表示用户的常用信息为使用的设备id为5432,在question_id为113的题目上,回答错误
请你写SQL查找每个学校用户的平均答题数目(说明:某学校用户平均答题数量计算方式为该学校用户答题总次数除以答过题的不同用户个数)根据示例,你的查询应返回以下结果(结果保留4位小数),注意:结果按照university升序排序!!!
| university | avg_answer_cnt |
|---|---|
| 北京大学 | 1.0000 |
| 复旦大学 | 2.0000 |
| 山东大学 | 2.0000 |
| 浙江大学 | 3.0000 |
解释:
第一行:北京大学总共有2个用户,2138和6543,2个用户在question_practice_detail里面答了2题,平均答题数目为2/2=1.0000
....
最后一行:浙江大学总共有1个用户,2315,这个用户在*question_practice_detail里面答了3题,平均答题数目为3/1=3.0000*
区分答过题的用户的平均答题数,和用户的平均答题数。
如果是答过题的,连表时就只需要保留在question_practice_detail有记录的即可。
如果是所有用户的,那就得保留所有用户,用外连接
select up.university, count(qpd.question_id)/count(distinct up.device_id) avg_answer_cnt
from user_profile up join question_practice_detail qpd
on up.device_id = qpd.device_id
group by up.university
order by up.university
计算25岁以上和以下的用户数量
题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量
本题注意:age为null 也记为 25岁以下
示例:user_profile
| id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
|---|---|---|---|---|---|---|---|---|
| 1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
| 2 | 3214 | male | 复旦大学 | 4 | 15 | 5 | 25 | |
| 3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
| 4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
| 5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
| 6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
| 7 | 4321 | male | 26 | 复旦大学 | 3.6 | 9 | 6 | 52 |
根据示例,你的查询应返回以下结果:
| age_cut | number |
|---|---|
| 25岁以下 | 4 |
| 25岁及以上 | 3 |
if 和case可以把列做一个映射,映射成另外一个新的列,然后可以根据这个新的列分组
select if(age>=25, "25岁及以上", "25岁以下") age_cnt, count(gender) number
from user_profile
group by age_cnt