notion原文地址 SQL数据库实战题_面试必刷+解析_牛客题霸_牛客网
基础练习
1. 常用字段
distinct() | 去重 |
---|
MAX() | | avg() | 求平均值 | union all | 将多个查询结果合在一起,不去重 | union | 将多个查询结果合在一起 去重 | SUBSTRING_INDEX(profile, ‘,’, -1) | 截取最后一个,如果是 -2 就是截取最后两个 |
2. 小技巧
-
取表中的前几条数据
select device_id from user_profile limit 0, 2;
select * from user_profile where rownum <= 2
-
某个字段不为空
SELECT device_id, gender, age, university from user_profile where age is not null
-
字段中包含某些文字
SELECT device_id, age, university
from user_profile
where university LIKE '%北京%'
-
多列分组
SELECT gender, university,
COUNT(1) user_num,
AVG(active_days_within_30) avg_active_day,
AVG(question_cnt) avg_question_cnt
from user_profile
group by gender, university
-
Group by 跟 where, having 联用
- where 是在分分组前对数据进行过滤,不能包含聚合函数
- have 是筛选出符合条件的组,是在分组后
SELECT university,
AVG(question_cnt) avg_question_cnt,
AVG(answer_cnt) avg_answer_cnt
from user_profile
where age > 18
GROUP by university
HAVING AVG(question_cnt) < 5
or AVG(answer_cnt) < 20
-
case 函数 知识 CASE函数 是一种多分支的函数,可以根据条件列表的值返回多个可能的结果表达式中的一个。可用在任何允许使用表达式的地方,但不能单独作为一个语句执行。分为:简单CASE函数搜索CASE函数 简单 CASE函数 SELECT 班号 ,班名,
CASE 系号
WHEN 1 THEN '软件工程系'
WHEN 2 THEN '计算机系'
WHEN 3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
计算测试表达式,按从上到下的书写顺序将测试表达式的值与每个WHEN子句的简单表达式进行比较。如果某个简单表达式的值与测试表达式的值相等,则返回第一个与之匹配的WHEN子句所对应的结果表达式的值。如果所有简单表达式的值与测试表达式的值都不相等,若指定了ELSE子句,则返回ELSE子句中指定的结果表达式的值;若没有指定ELSE子句,则返回NULL。 例48. 查询班级表中的学生的班号、班名、系号和班主任号,并对系号作如下处理:当系号为1时,显示 “计算机系”;当系号为2时,显示 “软件工程系”;当系号为3时,显示 “物联网系”。 SELECT 班号 ,班名,
CASE 系号
WHEN 1 THEN '软件工程系'
WHEN 2 THEN '计算机系'
WHEN 3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
搜索CASE函数 CASE
WHEN 布尔表达式1 THEN 结果表达式1
WHEN 布尔表达式2 THEN 结果表达式2 …
WHEN 布尔表达式n THEN 结果表达式n
[ ELSE 结果表达式n+1 ]
END
按从上到下的书写顺序计算每个WHEN子句的布尔表达式。返回第一个取值为TRUE的布尔表达式所对应的结果表达式的值。如果没有取值为TRUE的布尔表达式,则当指定了ELSE子句时,返回ELSE子句中指定的结果;如果没有指定ELSE子句,则返回NULL。 例48用搜索CASE来做: SELECT 班号 ,班名,
CASE
WHEN 系号=1 THEN '软件工程系'
WHEN 系号=2 THEN '计算机系'
WHEN 系号=3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
例49.查询“M01F011”号课程的考试情况,列出学号、课程号和成绩,同时将百分制成绩显示为等级。 SELECT 学号,课程号,
CASE
WHEN 成绩 >= 90 THEN '优'
WHEN 成绩 BETWEEN 80 AND 89 THEN '良'
WHEN 成绩 BETWEEN 70 AND 79 THEN '中'
WHEN 成绩 BETWEEN 60 AND 69 THEN '及格'
WHEN 成绩 <60 THEN '不及格'
END 成绩
FROM 成绩表
WHERE 课程号 = 'M01F011'
CASE函数(续) 例50.统计每个班男生和女生的数量各是多少,统计结果的表头为,班号,男生数量,女生数量。 SELECT 班号,
COUNT(CASE WHEN 性别=‘男’ THEN ‘男’ END) 男生数,
COUNT(CASE WHEN 性别=‘女’ THEN ‘女’ END) 女生数
FROM 学生表 GROUP BY 班号
例51.判断成绩的等级,85-100为“优”,70-84为“良”,60-69为“及格”,60以下为“不及格”,并统计每一等级的人数。 SELECT
CASE
WHEN GRADE BETWEEN 85 AND 100 THEN '优'
WHEN GRADE BETWEEN 70 AND 84 THEN '良'
WHEN GRADE BETWEEN 60 AND 69 THEN '及格'
ELSE '不及格'
END 等级, COUNT(*) 人数
FROM SC
GROUP BY
CASE
WHEN GRADE BETWEEN 85 AND 100 THEN '优'
WHEN GRADE BETWEEN 70 AND 84 THEN '良'
WHEN GRADE BETWEEN 60 AND 69 THEN '及格'
ELSE '不及格'
END
题解 题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量 SELECT CASE WHEN age < 25 OR age IS NULL THEN '25岁以下'
WHEN age >= 25 THEN '25岁及以上'
END age_cut,COUNT(*)number
FROM user_profile
GROUP BY age_cut
示例:user_profile https://uploadfiles.nowcoder.com/images/20210928/999991344_1632828974694/7219DA906D0C14B655E857C7349E6017 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210928/999991344_1632831829937/75D997B10141AD2740283AC28486E68D -
日期函数
DateOfWeek(‘1997-06-19’) | 这天是周几:0是周一,6是周日 |
---|
WeekDay(‘1997-06-19 14:19:00’) | 当前时间是周几:0周一 | DayOfMonth(‘1997-06-19’) | 这天是几号 19 | DayOfYear(‘1997-06-19’) | 这天是一年中的第几天 | Year(date) | 获取年份 | Month(date) | 获取月份 | DayName(date) | 返回星期的英文名 | MonthName(date) | 返回月份的英文名 | Quarter(date) | 返回季度 1~4 | Week(date) | 返回这一周是一年中的第几周 0~52 | Week(date,first) | 返回这一周是一年中的第几周,但是可以指定从周几开始,first = 0 从周日开始, first = 1 从周一开始 | Hour(time) | 返回当前时间是第几小时 0~23 | Minute(time) | 0~59 | Second(time) | 0~59 | Period_add(P,N) | 增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。 |
例如:若返回 199706 select PERIOD_ADD(9704,2) | | Period_diff(P1,P2) | 返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。 且p1 > p2返回是正 例如:求97年6月到 00年8月之间有几个月 select PERIOD_DIFF(200008, 9706); | -
窗口函数
-
与group by 的区别
group by 分组后会去重,减少原表的行数 而窗口函数可以分组但不会·去重,不会改变原表的行数;并且可以排序
-
窗口函数只能写在select后面 -
窗口函数分类
- rank
- dense_rank
- row_number
区别:
学号 | 分数 | 班级 |
---|
1 | 99 | 1 | 2 | 98 | 1 | 3 | 99 | 2 | 4 | 97 | 2 | 5 | 99 | 1 | 6 | 100 | 2 |
select *,
rank() over (partition by 班级 order by 分数 desc) as ranking,
dense_rank() over (partition by 班级 order by 分数desc) as dese_rank,
row_number() over (partition by 班级 order by 分数desc) as row_num
from table_name
结果:
学号 | 分数 | 班级 | ranking | dese_rank | row_num |
---|
6 | 99 | 1 | 1 | 1 | 1 | 1 | 99 | 1 | 1 | 1 | 2 | 3 | 98 | 1 | 3 | 2 | 3 | 5 | 100 | 2 | 1 | 1 | 1 | 2 | 100 | 2 | 1 | 1 | 2 | 4 | 97 | 2 | 3 | 2 | 3 |
-
连接查询
-
内连接:结果只包含符合条件的行
-
显示内连接 select difficult_level,
count(if(qpd.result='right', 1, null)) / count(qpd.question_id) as correct_rate
from user_profile as up
inner join question_practice_detail as qpd
on up.device_id = qpd.device_id
inner join question_detail as qd
on qd.question_id = qpd.question_id
where up.university = '浙江大学'
group by qd.difficult_level
order by correct_rate asc;
-
隐式内连接 select difficult_level,
avg(if(qpd.result='right', 1, 0)) as correct_rate
from user_profile as up, question_practice_detail as qpd, question_detail as qd
where up.university = '浙江大学'
and up.device_id = qpd.device_id
and qd.question_id = qpd.question_id
group by qd.difficult_level
order by correct_rate asc;
-
外连接:连接结果包含符合条件的行,也包括不符合条件的行
-
左外连接:以左表为基准,左表全部展示,右表符合条件的展示,不符合条件的为null SELECT COUNT(date2) / COUNT(date1) AS avg_ret
FROM
(SELECT DISTINCT device_id, date AS date1
FROM question_practice_detail) AS qpd1
LEFT join
(SELECT DISTINCT device_id, date AS date2
FROM question_practice_detail) AS qpd2
ON qpd1.device_id = qpd2.device_id
and date2 = DATE_ADD(date1, interval 1 day)
-
右外连接: 以右表为基准,右表全部展示,左表符合条件的展示,不符合条件的为null SELECT COUNT(date2) / COUNT(date1) AS avg_ret
FROM
(SELECT DISTINCT device_id, date AS date2
FROM question_practice_detail) AS qpd2
right join
(SELECT DISTINCT device_id, date AS date1
FROM question_practice_detail) AS qpd1
ON qpd1.device_id = qpd2.device_id
and date2 = DATE_ADD(date1, interval 1 day)
3. 例题
-
SQL24 统计每个用户的平均刷题数 描述 题目:运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据 示例:user_profile https://uploadfiles.nowcoder.com/images/20210928/999991344_1632830351547/83841168E15DBA85CE3594D85175D7E7 示例:答题明细表question_practice_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629873138701/7E8C6C3B40F0F6131BFB50C711670B30 示例:question_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629873102727/EC0F6399653CACAFBD580C91F8876FD1 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20211109/999991344_1636451192884/CDE33899BDD51928D51BD9BAA98FF32F 分析:
限定条件: university = '山东大学'
不同难度: 按照题目难度分类
平均刷题数: 总题目 / 总人数
SELECT up.university,
qd.difficult_level,
COUNT(qpd.question_id) / COUNT(DISTINCT qpd.device_id)
FROM question_practice_detail qpd
left JOIN user_profile up
on up.device_id = qpd.device_id
left JOIN question_detail qd
on qpd.question_id = qd.question_id
WHERE up.university = '山东大学'
GROUP BY qd.difficult_level
-
统计每个学校各难度的用户平均刷题数 描述 题目:运营想要计算每个学校用户不同难度下的用户平均答题题目数情况,请你取出相应数据 用户信息表:user_profile https://uploadfiles.nowcoder.com/images/20210928/999991344_1632828858893/3828EF6CA35F43648637D472E1773B32 题库练习明细表:question_practice_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629872851900/2FA3BEC5786F91F8565CB783FF410CA2 表:question_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629872873356/9098ACACD4BA7F3E5C9117FE1B551B80 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20211028/999991344_1635406692880/C85A0D1B7F81E0BA195B05205F04A75C 分析:
每个学校:按学校名分类
各个难度:按题目难度分类
平均刷题数:总题目除以总人数
注意谁是主表
SELECT us.university,
qd.difficult_level,
COUNT(qpd.question_id) / COUNT(DISTINCT qpd.device_id) avg_answer_cnt
FROM question_practice_detail qpd
LEFT JOIN user_profile us
on us.device_id = qpd.device_id
LEFT JOIN question_detail qd
on qd.question_id = qpd.question_id
GROUP BY university, difficult_level
-
SQL25 查找山东大学男生的GPA 描述 题目:现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。 示例:user_profile https://uploadfiles.nowcoder.com/images/20210928/999991344_1632828942213/AD137E285DB522E842618F0954CEF067 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210825/999991344_1629874520344/B367F3B94479F5562E1F3CB07F39D3A1 分析
分别查看: union all
限定条件:学校为山东大学 or 性别为男性
SELECT device_id, gender, age, gpa
FROM user_profile up
where up.university = '山东大学'
UNION ALL
SELECT device_id, gender, age, gpa
FROM user_profile up
where up.gender = 'male'
-
SQL26 计算25岁以上和以下的用户数量 描述 题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量 本题注意:age为null 也记为 25岁以下 示例:user_profile https://uploadfiles.nowcoder.com/images/20210928/999991344_1632828974694/7219DA906D0C14B655E857C7349E6017 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210928/999991344_1632831829937/75D997B10141AD2740283AC28486E68D 分析:
使用case函数
SELECT
case
when age < 25 or isnull(age) then '25岁以下'
when age >= 25 then '25岁及以上'
end age_cut,
count(*) number
FROM user_profile
GROUP BY age_cut;
-
SQL27 查看不同年龄段的用户明细 描述 题目:现在运营想要将用户划分为20岁以下,20-24岁,25岁及以上三个年龄段,分别查看不同年龄段用户的明细情况,请取出相应数据。(注:若年龄为空请返回其他。) 示例:user_profile https://uploadfiles.nowcoder.com/images/20210925/999991344_1632559724473/28744AF08FD7048458538C9BC098A0BD 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20211018/999991344_1634545835989/62FBCEE9A212715D0583D408F91DDF68 SELECT device_id, gender,
case
when age < 20 then '20岁以下'
when age between 20 and 24 then '20-24岁'
when age >= 25 then '25岁及以上'
else '其他'
END age_cut
from user_profile
-
SQL28 计算用户8月每天的练题数量 描述 题目:现在运营想要计算出2021年8月每天用户练习题目的数量,请取出相应数据。 示例:question_practice_detail https://uploadfiles.nowcoder.com/images/20210809/373115_1628510778730/35869B8BF490DC7526BD4B3A99D80A3F 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20211021/999991344_1634818723100/2F705925643BDF829C4D494647BC0617 SELECT DAY(date) day, count(question_id) question_cnt
from question_practice_detail
where MONTH(date) = 8 and YEAR(date) = 2021
GROUP by day;
-
SQL29 计算用户的平均次日留存率 描述 题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。 示例:question_practice_detail https://uploadfiles.nowcoder.com/images/20210809/373115_1628511730741/35869B8BF490DC7526BD4B3A99D80A3F 根据示例,你的查询应返回以下结果:
SELECT COUNT(DISTINCT qpd2.device_id) / COUNT(DISTINCT qpd1.device_id) AS avg_ret
FROM question_practice_detail qpd1
LEFT join (SELECT * from question_practice_detail) AS qpd2
ON qpd1.device_id = qpd2.device_id
and qpd2.date = DATE_ADD(qpd1.date, interval 1 day)
正确实例
SELECT COUNT(date2) / COUNT(date1) AS avg_ret
FROM
(SELECT DISTINCT device_id, date AS date1
FROM question_practice_detail) AS qpd1
LEFT join
(SELECT DISTINCT device_id, date AS date2
FROM question_practice_detail) AS qpd2
ON qpd1.device_id = qpd2.device_id
and date2 = DATE_ADD(date1, interval 1 day)
-
SQL30 统计每种性别的人数 描述 题目:现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个性别的用户分别有多少参赛者,请取出相应结果 示例:user_submit https://uploadfiles.nowcoder.com/images/20210809/373115_1628513042757/ADEF3557414F576FBEB396BA7DAEF385 根据示例,你的查询应返回以下结果:
select
SUBSTRING_INDEX(profile, ',', -1) AS gender,
COUNT(1) number
from user_submit us
GROUP BY gender
-
SQL32 截取出年龄 描述 题目:现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个年龄的用户分别有多少参赛者,请取出相应结果 示例:user_submit https://uploadfiles.nowcoder.com/images/20210809/373115_1628513042757/ADEF3557414F576FBEB396BA7DAEF385 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210809/373115_1628514780113/2CA6A3C989804B7CC2C30A7FCD73563B
select SUBSTRING_INDEX(
SUBSTRING_INDEX(profile, ',', -2), ',', 1) as age, COUNT(1) AS number
from user_submit
GROUP BY age
-
SQL33 找出每个学校GPA最低的同学 描述 题目:现在运营想要找到每个学校gpa最低的同学来做调研,请你取出每个学校的最低gpa。 示例:user_profile https://uploadfiles.nowcoder.com/images/20210810/373115_1628564666413/89985A626751183577CBADEEBFA22DB2 根据示例,你的查询结果应参考以下格式: https://uploadfiles.nowcoder.com/images/20211021/999991344_1634818944611/05F53DFC1E484A1237B951CA540956BC
SELECT device_id,university,gpa
FROM
(SELECT *,
RANK() over (PARTITION BY university ORDER BY gpa) ranking
FROM user_profile) us
WHERE us.ranking = 1;
-
SQL34 统计复旦用户8月练题情况 描述 题目: 现在运营想要了解复旦大学的每个用户在8月份练习的总题目数和回答正确的题目数情况,请取出相应明细数据,对于在8月份没有练习过的用户,答题数结果返回0. 示例:用户信息表user_profile https://uploadfiles.nowcoder.com/images/20211008/999991344_1633667279913/26BCEC9E23F27133C40AA13A0E3F8BE5 https://uploadfiles.nowcoder.com/images/20210928/999991344_1632831099120/BFA09F548D2B5CCC5BF6A7C9BA7EEAAA 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210810/373115_1628582518442/B290AA4057F416C6F9C704C65228A459
select up.device_id, up.university,
count(question_id) as question_cnt,
sum(if(qpd.result='right', 1, 0)) as right_question_cnt
from question_practice_detail as qpd
RIGHT join user_profile as up
on qpd.device_id = up.device_id and month(qpd.date) = 8
where up.university = '复旦大学'
group by up.device_id
-
SQL35 浙大不同难度题目的正确率 描述 题目:现在运营想要了解浙江大学的用户在不同难度题目下答题的正确率情况,请取出相应数据,并按照准确率升序输出。 示例: user_profile https://uploadfiles.nowcoder.com/images/20210810/373115_1628582834553/89985A626751183577CBADEEBFA22DB2 示例: question_practice_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629875499695/18E2999891374A475D0687CA9F989D83 示例: question_detail https://uploadfiles.nowcoder.com/images/20210825/999991344_1629875455150/032B2CC936860B03048302D991C3498F 根据示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20211021/999991344_1634819049484/CF498AB69F3681735FD9F6233A914B54
select difficult_level,
avg(if(qpd.result='right', 1, 0)) as correct_rate
from user_profile as up, question_practice_detail as qpd, question_detail as qd
where up.university = '浙江大学'
and up.device_id = qpd.device_id
and qd.question_id = qpd.question_id
group by qd.difficult_level
order by correct_rate asc;
-
SQL37 查找后多列排序 描述 题目:现在运营想要取出用户信息表中的年龄和gpa数据,并先按照gpa升序排序,再按照年龄升序排序输出,请取出相应数据。 用户信息表:user_profile https://uploadfiles.nowcoder.com/images/20210815/373115_1629034341633/6899BB86C71C91EB2C4D8CEBBCAA54BD 你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210825/999991344_1629879700881/539F7FC107F64CA65C2CA5255D5A9510 SELECT device_id, gpa, age
FROM user_profile
ORDER BY gpa, age ASC
-
SQL39 21年8月份练题总数 描述 题目: 现在运营想要了解2021年8月份所有练习过题目的总用户数和练习过题目的总次数,请取出相应结果 示例:question_practice_detail https://uploadfiles.nowcoder.com/images/20210815/373115_1629036174965/4EE68116010D69F00DDA84ACB38331CA 根据的示例,你的查询应返回以下结果: https://uploadfiles.nowcoder.com/images/20210815/373115_1629036387046/12805D31CDA577D0CACF0F9F67928817
SELECT COUNT(DISTINCT device_id) AS did_cnt,
COUNT(question_id) AS question_cnt
from question_practice_detail
where YEAR(date) = 2021 and MONTH(date) = 8
|