题1
用户信息表:user_profile
查询结果案例:
题目:作为牛客网的数据分析师,现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营,请取出平均发贴数低于5的学校或平均回帖数小于20的学校。
解析:
- 限定条件:平均发贴数低于5或平均回帖数小于20的学校,
avg(question_cnt)<5 or avg(answer_cnt)<20
,聚合函数结果作为筛选条件时,不能用where,而是用having语法,配合重命名即可; - 按学校输出:需要对每个学校统计其平均发贴数和平均回帖数,因此
group by university
- 表头重命名:as
sql:
select
university,AVG(question_cnt) as avg_question_cnt,
AVG(answer_cnt) as avg_answer_cnt
from user_profile
GROUP BY university
HAVING avg_question_cnt<5 or avg_answer_cnt<20;
Round(AVG(gpa),1)
解释:Round函数是保留几位小数,所以这个意思就是gpa的平均值保留1位小数
distanct 唯一
MAX(age)
解释:MAX聚合函数,age的最大值
IN
in常用于where表达式中,其作用是查询某个范围内的数据
找到学校为北大、复旦和山大的同学
select device_id,gender,age,university,gpa from user_profile
where university in('北京大学','复旦大学','山东大学');
NOT IN
//除字段以外的
is NOT NULL
//不为空
BETWEEN .. AND..
范围限定,例如 where age BETWEEN 20 and 23;//age在20~23的
limit(偏移量,个数)
//注意偏移量不包括在内,比如limit (1,3),查找第2,3,4条数据
Order by desc 降序排列
ASC升序
题2
用户信息表:user_profile
题库练习明细表:question_practice_detail
表:question_detail
根据示例,你的查询应返回以下结果:
计算每个学校用户不同难度下的用户平均答题题目数情况,请取出相应数据
解析:
- 每个学校:按学校分组
group by university
- 不同难度:按难度分组
group by difficult_level
- 平均答题数:总答题数除以总人数
count(qpd.question_id) / count(distinct qpd.device_id)
- 来自上面信息三个表,需要联表,up与qpd用device_id连接,qd与qpd用question_id连接。
- 表头重命名:as
sql:
SELECT
university,difficult_level,
count(qpd.question_id)/count(distinct qpd.device_id) as avg_answer_cnt
from question_practice_detail qpd
inner join question_detail qd
on qd.question_id=qpd.question_id
inner join user_profile as up
on up.device_id=qpd.device_id
group by university,qd.difficult_level;
联合查询
- UNION 去重
- UNION ALL 不去重
例子:
分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。
这里需要把山东大学 和 男的 分别筛选出来再用UNION ALL黏在一起 UNION默认去重 所以这里用UNION ALL
SELECT device_id,gender,age,gpa
from user_profile
where university='山东大学'
union all
SELECT device_id,gender,age,gpa
from user_profile
where gender='male';
条件函数 IF
if(x=n,a,b)表示如果x=n,则返回a,否则就是b了。
user_profile
根据示例,你的查询应返回以下结果:
题目:将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量
解析:
- 年龄划分为两段:
if(age>=25, "25岁以及上", "25岁以下")
- 统计用户数量:count,每个段分别统计,用group by age_cut分组
- 当然本题也可以用union all解决,不过用if更直观
- 表头重命名
- 注意题目描述的示例和testcase结果不一致!!
- 如果采用unionall解决,针对年龄为空的记录,需要明确是划分到哪边
- 不同段的释义要根据testcase调整(以及上 not 及以上)
sql:
select
if(age>=25,'25岁及以上','25岁以下') as age_cut,
count(device_id) as Number
from user_profile
group by age_cut;
case when(多值判断)..then..else..end
例子:将用户划分为20岁以下,20-24岁,25岁及以上三个年龄段,分别查看不同年龄段用户的明细情况
user_profile
根据示例,你的查询应返回以下结果:
sql:
select device_id,gender,
case when age between 20 and 24 then '20-24岁'
when age>=25 then '25岁以上'
else '其他' end as age_cut
from user_profile;
day,mongth,year关键字
day(yy-mm-dd格式参数)//会转化成day
mongth(yy-mm-dd格式参数)//会转化成month
year(yy-mm-dd格式参数)//会转化成year
使用mysql时一定要注意,尽量不要使用它的保留字作为表名或者列名,否则会出现莫名其妙的错误。如果之前用了,在sql语句中就用``包括起来。
模糊查询
like ' % '
例子:查找以张开头的人 select ...where name like '张%'
查找中间包含x的字段 select ...where name like '%x%'
查找以m结尾的字段 select ...where name like '%m'
sum函数和count函数
1.sum
(1)sum()函数里面的参数是列名的时候,是计算列名的值的相加,而不是有值项的总数。
(2)sum(条件表达式),如果记录满足条件表达式就加1,统计满足条件的行数
例如:sum(if month(date)=8,1,0)//如果date是8月份就加一
没有group by,就只能有一条,sum得到的是总数
有group by,就分组了,sum得到的是分组后,每一个组的总数
2.count
(1)COUNT()函数里面的参数是列名的的时候,那么会计算有值项的次数。(NULL 不计入, 但是' '值计入)
(2)COUNT(*)可以计算出行数,包括null
(3)COUNT(1)也可以计算出行数,1在这里代表一行
(4)COUNT(column)对特定的列的值具有的行数进行计算,不包含NULL值
(5)COUNT(条件表达式),不管记录是否满足条件表达式,只要非NULL就加1
having的用法
语法:
group by 字段 having 条件判断;
SELECT dept,COUNT(user_name) count_tmp
FROM ec_uses GROUP BY dept HAVING count_tmp>1;
所以having子句对我们筛选分组后的数据非常方便
注意:having后面跟的条件判断的字段必须是聚合函数返回的结果,否则sql会报错
连表查询
内连接inner join on(只写join on 也是内连接)
左连接left join on
右连接right join on
因为sql很久没练习了,很多都陌生了,今日从入门开始做,一切豁然开朗