SQL刷题记录贴
1.题目:现在运营想要对用户的年龄分布开展分析,在分析时想要剔除没有获取到年龄的用户,请你取出所有年龄值不为空的用户的设备ID,性别,年龄,学校的信息。
错误:select device_id,gender,age,university from user_profile where age!=null;
在 SQL 中,判断 NULL
的值需要使用 IS NULL
或 IS NOT NULL
,而不能直接用 != null
来比较。NULL
在 SQL 中表示一个未知的值,因此不能使用普通的比较运算符(如 !=
或 =
)进行比较。
正确:
select device_id,gender,age,university from user_profile where age is not null;
select device_id,gender,age,university from user_profile where age!='';
select device_id,gender,age,university from user_profile where age<>'';
2.题目:运营想要知道复旦大学学生gpa最高值是多少,请你取出相应数据,根据输入,你的查询应返回以下结果,结果保留到小数点后面1位
正确:注意起别名和保留一位小数
select round(max(gpa),1) gpa from user_profile where university='复旦大学';
3.题目:现在运营想要对每个学校不同性别的用户活跃情况和发帖数量进行分析,请分别计算出每个学校每种性别的用户数、30天内平均活跃天数和平均发帖数量。
错误:select gender,university,count(gender) user_num,round(avg(active_days_within_30),1) avg_active_day,round(avg(question_cnt),1) avg_question_cnt from user_profile order by (gender,university) desc group by (gender,university) ;
group by和 order by后面不加括号,order by在group by后面
正确:
select gender, university, count(gender) user_num, round(avg(active_days_within_30), 1) avg_active_day, round(avg(question_cnt), 1) avg_question_cnt from user_profile group by gender, university order by gender asc,university asc;
4.题目:现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营,请取出平均发贴数低于5的学校或平均回帖数小于20的学校。
错误:
select university,round(avg(question_cnt),3) avg_question_cnt,round(avg(answer_cnt),3) avg_answer_cnt from user_profile group by university having avg_question_cnt <5 or answer_cnt<20 ;
注意!!!
在 SQL 查询中,执行的顺序大致如下:
FROM
: 从哪个表或视图获取数据。WHERE
: 过滤数据。GROUP BY
: 按照指定的列对数据进行分组。HAVING
: 对分组后的数据进行过滤(通常用于聚合条件)。SELECT
: 从分组后的数据中选择列。ORDER BY
: 对结果进行排序。LIMIT
: 限制返回的结果行数(如果有的话)。
所以HAVING不能使用select中的别名!
5.
运营想要了解每个学校答过题的用户平均答题数量情况,请你取出数据。
正确:
select university,(count(question_id)/count(distinct(u.device_id))) avg_answer_cnt from user_profile u join question_practice_detail q on u.device_id=q.device_id group by university order by university ;
一定要加distinct!
6.题目:运营想要计算一些参加了答题的不同学校、不同难度的用户平均答题量,请你写SQL取出相应数据
select u.university,s.difficult_level,round(count(s.question_id)/count(distinct u.device_id),
4
) avg_answer_cnt
from user_profile u join
(select p.device_id,p.question_id,q.difficult_level from question_practice_detail p left join question_detail q on p.question_id=q.question_id) s
on u.device_id=s.device_id GROUP BY u.university, s.difficult_level;
为什么需要两个字段:
- 如果你只按
u.university
进行分组,你将无法区分不同难度的题目,只能得到每个学校的总答题量。 - 如果你只按
s.difficult_level
进行分组,你将无法区分不同学校的答题量。 - 因此,使用 两个字段 (
university
和difficult_level
)来分组,是为了获取每个学校和每个难度题目的详细统计。
具体例子:
假设有以下数据:
- 学校 A 和学校 B 的用户分别参与了难度为
easy
和medium
的题目。 - 如果我们只按学校分组,难度将无法区分;
- 如果只按难度分组,学校也无法区分。
因此,按学校和难度同时分组能够准确计算每个学校和每个难度下的答题统计数据。
7.运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据
报错:Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'niuke.u.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
原因:
根据 SQL 标准,SELECT
列表中的列要么应该包含在 GROUP BY
子句中,要么应该使用聚合函数进行处理。
最直接的方法是修改 SQL 查询,使得 SELECT 列表中的所有列都包含在 GROUP BY 子句中,或者使用聚合函数。
8.
UNION
:合并多个查询的结果集,并去除重复的行。它在返回结果时会进行去重操作。UNION ALL
:合并多个查询的结果集,但不会去除重复的行。返回结果中可能包含重复的记录。
9.题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的留存率。请你取出相应数据。
第一眼看,完全没有思路!!!
select count(distinct q2.device_id,q2.date)/count(distinct q1.device_id,q1.date) as avg_ret
from question_practice_detail as q1 left join
question_practice_detail as q2
on q1.device_id = q2.device_id
and datediff(q2.date,q1.date)=1;
COUNT(DISTINCT q1.device_id, q1.date)
计算的是,q1
表中 不同设备和日期的组合 的数量。
10.题目:现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个性别的用户分别有多少参赛者,请取出相应结果。
str
:要操作的字符串。delim
:分隔符,用来拆分字符串。count
:返回子字符串的数量。- 如果
count
是正数,表示从左侧开始计算,返回从左到右第count
次出现分隔符之前的所有部分。 - 如果
count
是负数,表示从右侧开始计算,返回从右到左第count
次出现分隔符之前的所有部分。
- 如果
假设有以下字符串:'apple,banana,cherry'
我们希望提取分隔符 ,
前面的第一个部分(即 apple
)
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', 1) AS first_part;
我们希望提取分隔符 ,
后面的最后一个部分(即 cherry
)。
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', -1) AS last_part;
我们希望提取第二部分(即 banana
)。
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('apple,banana,cherry,date', ',', 2), ',', -1) AS second_part;
11.blog_url是sql中的一个字段,举例http:/url/bisdgboy777,我怎么提取最后斜杠后的bisdgboy777?SELECT SUBSTRING_INDEX(blog_url, '/', -1) AS extracted_value
FROM your_table;
在 MySQL 示例中,SUBSTRING_INDEX
函数用于获取最后一个斜杠后的部分。
12.select substring_index(substring_index(profile,',',3),',',-1) as age
,count(age) as number from user_submit group by age;
为什么count(age)不正确,count(*)正确
`count(age)` 只会统计 `age` 列中非 `NULL` 的值
`count(*)` 计算的是所有行的数量,包括 `NULL` 和非 `NULL` 的值