目录
非技术快速入门
SQL29 计算用户的平均次日留存率
SQL34 统计复旦用户8月练题情况
SQL35 浙大不同难度题目的正确率
SQL进阶挑战
SQL14 SQL类别高难度试卷得分的截断平均值
SQL19 未完成试卷数大于1的有效用户
SQL20 月均完成试卷数不小于3的用户爱作答的类别
SQL25 满足条件的用户的试卷完成数和题目练习数
SQL26 每个6/7级用户活跃情况
SQL28 第二快/慢用时之差大于试卷时长一半的试卷
SQL29 连续两次作答试卷的最大时间窗
SQL31 未完成率较高的50%用户近三个月答卷情况
SQL32 试卷完成数同比2020年的增长率及排名变化
SQL35 每月及截止当月的答题情况
SQL38 筛选限定昵称成就值活跃日期的用户
SQL39 筛选昵称规则和试卷规则的作答记录
SQL40 根据指定记录是否存在输出不同情况
SQL41 各用户等级的不同得分表现占比
SQL43 注册当天就完成了试卷的名单第三页
SQL46 大小写混乱时的筛选统计
全部题目
SQL12 获取每个部门中当前员工薪水最高的相关信息
SQL18 获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
SQL21 查找在职员工自入职以来的薪水涨幅情况
SQL23 对所有员工的薪水按照salary降序进行1-N的排名
SQL24 获取所有非manager员工当前的薪水情况
SQL25 获取员工其当前的薪水比其manager当前薪水还高的相关信息
SQL26 汇总各个部门当前员工的title类型的分配数目
SQL59 获取有奖金的员工相关信息
SQL60 统计salary的累计和running_total
SQL61 给出employees表中排名为奇数行的first name
SQL65 异常的邮件概率
SQL67 牛客每个人最近的登录日期(二)
SQL68 牛客每个人最近的登录日期(三)
SQL69 牛客每个人最近的登录日期(四)
SQL70 牛客每个人最近的登录日期(五)
SQL71 牛客每个人最近的登录日期(六)
SQL74 考试分数(三)
SQL75 考试分数(四)
SQL76 考试分数(五)
SQL80 牛客的课程订单分析(四)
SQL81 牛客的课程订单分析(五)
SQL82 牛客的课程订单分析(六)
SQL83 牛客的课程订单分析(七)
SQL86 实习广场投递简历分析(三)
SQL88 最差是第几名(二)
SQL90 获得积分最多的人(二)
SQL91 获得积分最多的人(三)
SQL93 网易云音乐推荐(网易校招笔试真题)
with t as (select distinct device_id, date from question_practice_detail)
select count(*)/(select count(*) from t) as avg_ret from t a
join t b on a.device_id = b.device_id and datediff(b.date, a.date) = 1;
select a.device_id, university,
count(question_id) as question_cnt,
sum(if(result='right', 1, 0)) as right_question_cnt
from user_profile a left join question_practice_detail b on a.device_id = b.device_id and
month(date) = 8 where university = '复旦大学' group by a.device_id, university;
select difficult_level, sum(if(result='right', 1, 0))/count(*) as correct_rate
from user_profile left join question_practice_detail using(device_id) join question_detail
using(question_id) where university = '浙江大学' group by difficult_level order by correct_rate;
select tag, difficulty,
round((sum(score)-max(score)-min(score))/(count(*)-2), 1) as clip_avg_score
from exam_record join examination_info using(exam_id)
where score is not null and tag = 'SQL' and difficulty = 'hard'
;
select uid, sum(if(submit_time is null, 1, 0)) as incomplete_cnt,
sum(if(submit_time is not null, 1, 0)) as complete_cnt,
group_concat(distinct concat(date(start_time), ':', tag) order by start_time SEPARATOR ';') as detail
from exam_record join examination_info using(exam_id) where year(start_time) = 2021
group by uid
having complete_cnt >= 1 and incomplete_cnt between 2 and 4
order by incomplete_cnt desc;
select tag, count(*) as tag_cnt from exam_record join examination_info using(exam_id)
where uid in
(select uid
from exam_record
group by uid, date_format(start_time, '%Y%m')
having count(submit_time) >= 3) group by tag order by tag_cnt desc;
with t as (
select uid from exam_record
where exam_id in (select exam_id from examination_info where tag = 'SQL' and difficulty = 'hard') and uid in (select uid from user_info where level = 7) group by uid having avg(score) > 80
)
select a.uid, max(exam_cnt) as exam_cnt, max(ifnull(question_cnt, 0)) as question_cnt from
(select uid, count(exam_id) over (partition by uid, date(start_time)) as exam_cnt from exam_record where year(start_time) = 2021 and uid in (select * from t)) a
left join
(select uid, count(question_id) over (partition by uid, date(submit_time)) as question_cnt from practice_record
where year(submit_time) = 2021 and uid in (select * from t)) b
using(uid) group by a.uid order by exam_cnt, question_cnt desc
;
# 所有日期都要去重
select uid, ifnull(s1.act_month_total, 0) as act_month_total,
ifnull(s2.act_days_2021, 0) as act_days_2021,
count(distinct(if(year(a.submit_time)=2021, date(a.submit_time), null))) as act_days_2021_exam,
count(distinct(if(year(b.submit_time)=2021, date(b.submit_time), null))) as act_days_2021_question
from user_info left join exam_record a using(uid) left join practice_record b using(uid)left join (select uid, count(mo) as act_month_total from
(select distinct uid, date_format(submit_time, '%Y%m') as mo from exam_record
union
select distinct uid, date_format(submit_time, '%Y%m') as mo from practice_record
) s group by uid) s1 using(uid)
left join (select uid, count(mo) as act_days_2021 from
(select distinct uid, date(submit_time) as mo from exam_record
union
select distinct uid, date(submit_time) as mo from practice_record) s
where year(mo) = 2021 group by uid) s2 using(uid)
where level in (6, 7) group by uid order by act_month_total desc, act_days_2021 desc;
with t as (
select exam_id, duration, release_time, timestampdiff(minute, start_time, submit_time) as te
from exam_record join examination_info using(exam_id)
)
select exam_id, duration, release_time from
(select exam_id, te,duration,release_time, row_number() over (partition by exam_id order by te desc) as rk from t
union
select exam_id, te,duration,release_time, row_number() over (partition by exam_id order by te) as rk from t) s where rk = 2
group by exam_id, duration, release_time having max(te)-min(te)>duration/2
order by exam_id desc;
select uid, days_window, round(cnt/(du+1)*days_window, 2) as avg_exam_cnt from
(select uid, count(distinct exam_id, date(start_time)) as cnt,
datediff(max(start_time), min(start_time)) as du from exam_record
where year(start_time)=2021 group by uid) a join
(select uid, max(du)+1 as days_window from
(select uid, datediff(lead(dt, 1) over(partition by uid order by dt), dt) as du from (select distinct uid, date(start_time) as dt from exam_record
where submit_time is not null and year(start_time) = 2021 order by uid, dt) s) s1 group by uid having days_window is not null) b
using(uid) order by days_window desc, avg_exam_cnt desc;
with t as (
select uid from
(select uid, percent_rank() over (order by per) as rk from
(select uid, if(count(distinct date(submit_time))=0, 1,
if(count(distinct date(submit_time))=count(*), 0, count(distinct date(submit_time))))/count(*) as per from exam_record left join examination_info using(exam_id) left join user_info using(uid) where tag = 'SQL' group by uid) s) s1 where rk >= 0.5
and uid in (select uid from user_info where level in (6, 7))
)
select uid, start_month, total_cnt, complete_cnt from
(select uid, date_format(start_time, '%Y%m') as start_month,
count(*) as total_cnt, count(submit_time) as complete_cnt,
dense_rank() over (partition by uid order by date_format(start_time, '%Y%m') desc) as rk
from exam_record where uid in (select * from t)
group by uid, start_month) s where rk <= 3 order by uid, start_month;
select tag, max(if(year=2020, exam_cnt, 0)) as exam_cnt_20,
max(if(year=2021, exam_cnt, 0)) as exam_cnt_21,
concat(round((max(if(year=2021, exam_cnt, 0))-max(if(year=2020, exam_cnt, 0)))/max(if(year=2020, exam_cnt, 0))*100, 1), '%') as growth_rate,
max(if(year=2020, rk, 0)) as exam_cnt_rank_20, max(if(year=2021, rk, 0)) as exam_cnt_rank_21,
max(if(year=2021, rk, 0))-max(if(year=2020, rk, 0)) as rank_delta
from (select *, rank() over (partition by year order by exam_cnt desc) as rk from
(select tag, year(start_time) as year, count(submit_time) as exam_cnt
from exam_record join examination_info using(exam_id)
where year(start_time) in (2020, 2021) and month(start_time) <= 6
group by tag, year having exam_cnt != 0) s) s1 group by tag having count(*) > 1
order by exam_cnt_20, growth_rate desc, exam_cnt_21 desc, exam_cnt_rank_21 desc;
with t as (
select date_format(start_time, '%Y%m') as mo,
count(distinct uid) as mau from exam_record
group by mo
)
select mo as start_month, mau, month_add_uv, max(month_add_uv) over (order by mo) as
max_month_add_uv, sum(month_add_uv) over (order by mo) as cum_sum_uv from
(select mo, mau, month_add_uv from t join
(select mo, sum(if(mo=minm, 1, 0)) as month_add_uv from
(select distinct uid, date_format(start_time, '%Y%m') as mo,
min(date_format(start_time, '%Y%m')) over (partition by uid) as minm
from exam_record) s group by mo) s using(mo)) s
order by start_month;
select uid, nick_name, achievement from
user_info left join exam_record a using(uid) left join practice_record b using(uid)
where left(nick_name, 2) = '牛客' and right(nick_name, 1) = '号'
and achievement BETWEEN 1200 and 2500
group by uid, nick_name, achievement
having DATE_FORMAT(max(a.submit_time), '%Y%m') = '202109'
or DATE_FORMAT(max(b.submit_time), '%Y%m') = '202109'
;
select uid, exam_id, round(sum(score)/count(submit_time)) as avg_score
from user_info left join exam_record using(uid) join examination_info using(exam_id)
where left(tag, 1) in ('c', 'C') and nick_name RLIKE '^牛客[0-9]{1,}号$|^[0-9]{1,}$'
group by uid, exam_id having avg_score is not null
order by uid, avg_score;
with t as (
select count(distinct uid) as cnt
from user_info left join exam_record using(uid)
where level = 0 group by uid having sum(if(submit_time is null, 1, 0)) > 2
)
select uid, ifnull(sum(if(submit_time is null and start_time is not null, 1, 0)), 0) as incomplete_cnt,
ifnull(round(sum(if(submit_time is null and start_time is not null, 1, 0))/count(*), 3), 0) as incomplete_rate
from user_info left join exam_record using(uid) where level = 0 group by uid
union
select uid, ifnull(sum(if(submit_time is null and start_time is not null, 1, 0)), 0) as incomplete_cnt,
ifnull(round(sum(if(submit_time is null and start_time is not null, 1, 0))/count(*), 3), 0) as incomplete_rate
from user_info left join exam_record using(uid) where (select * from t) is null and uid in (select uid from exam_record) group by uid order by incomplete_rate
;
with t as (
select level,
if(score>=90, '优', if(score>=75, '良', if(score>=60, '中', '差'))) as score_grade, count(*) as cnt
from user_info join exam_record using(uid)
where score is not null group by level, score_grade
)
select level, score_grade, round(cnt/total, 3) as ratio from
(select *, sum(cnt) over (partition by level) as total from t) s
order by level desc, ratio desc;
with t as (select uid from user_info where (uid, date(register_time)) in
(select uid, min(date(start_time)) as dt from exam_record where exam_id in (select exam_id from examination_info where tag = '算法') group by uid))
select uid, level, register_time, max(score) as max_score
from exam_record join user_info using(uid) where uid in (select * from t)
group by uid, level, register_time having max_score is not null
order by max_score desc limit 7, 3;
解法一
# with t as (
# select tag, count(*) as cnt
# from exam_record join examination_info using(exam_id)
# group by tag having cnt < 3
# )
# select lower(tag) as tag, count(*) as answer_cnt from exam_record join examination_info using(exam_id)
# where lower(tag) in (select tag from t) and tag not in (select tag from t) group by tag
# union
# select tag, count(*) as answer_cnt from exam_record a join examination_info using(exam_id)
# group by tag
# having (upper(tag), answer_cnt) in (select * from t) and tag != upper(tag)
# order by answer_cnt desc
# ;
解法二
with t as (
select tag, count(*) as answer_cnt
from exam_record join examination_info using(exam_id)
group by tag
)
# 找出大写的试卷作答数
select a.tag, b.answer_cnt
from t a join t b
on upper(a.tag) = b.tag and a.tag != b.tag and a.answer_cnt < 3;
select dept_no, emp_no, salary as maxSalary
from dept_emp join salaries using(emp_no, to_date)
where (dept_no, salary) in
(select dept_no, max(salary) from dept_emp join salaries using(emp_no) group by dept_no)
order by dept_no;
select emp_no, salary, last_name, first_name from employees join salaries using(emp_no)
where salary in (select max(salary) from salaries where salary not in (select max(salary) from salaries)) and to_date ='9999-01-01';
select emp_no, s2-s1 as growth
from (select emp_no, salary as s1 from salaries where from_date in (select hire_date from employees)) s1
join (select emp_no, salary as s2 from salaries where to_date = '9999-01-01') s2 using(emp_no)
order by growth;
select emp_no, salary, dense_rank() over (order by salary desc) as t_rank from salaries where to_date = '9999-01-01'
order by t_rank, emp_no;
select dept_no, emp_no, salary
from employees join dept_emp using(emp_no) join salaries using(emp_no)
where emp_no not in (select emp_no from dept_manager where to_date = '9999-01-01') and
dept_emp.to_date = '9999-01-01' and salaries.to_date = '9999-01-01';
select s1.emp_no, s2.emp_no as manager_no, s1.salary as emp_salary, s2.salary as manager_salary from
(select c.emp_no, a.dept_no, salary from dept_emp a
join dept_manager b on a.dept_no = b.dept_no and a.emp_no != b.emp_no join salaries c on a.emp_no = c.emp_no) s1
join (select emp_no, dept_no, salary from dept_manager join salaries using(emp_no)) s2
using(dept_no) where s1.salary > s2.salary;
select dept_no, dept_name, title, count(*) as count
from titles join dept_emp using(emp_no, to_date) join departments using(dept_no)
group by dept_no, dept_name, title
order by dept_no, title;
select emp_no, first_name, last_name, btype, salary,
if(btype=1, round(salary*0.1, 1), if(btype=2, round(salary*0.2, 1), round(salary*0.3, 1))) as bonus
from employees join emp_bonus using(emp_no) join salaries using(emp_no)
where to_date = '9999-01-01' order by emp_no;
select emp_no, salary, sum(salary) over (order by emp_no) as running_total from salaries
where to_date = '9999-01-01';
select first_name as first from employees
where first_name in (select first_name
from (select first_name, row_number() over (order by first_name) rk from employees) s where rk % 2 = 1);
select date,
round(sum(if(type='no_completed' and send_id not in (select id from user where is_blacklist = 1) and receive_id not in (select id from user where is_blacklist = 1), 1, 0))/sum(if(send_id not in (select id from user where is_blacklist = 1) and receive_id not in (select id from user where is_blacklist = 1), 1, 0)), 3) as p
from email group by date order by date;
select b.name as u_n, c.name as c_n, date
from login a join user b on a.user_id = b.id join client c on a.client_id = c.id
where (user_id, date) in (select user_id, max(date) from login group by user_id)
order by u_n
;
select round((select count(distinct a.user_id) as cnt from login a join login b on a.user_id = b.user_id and datediff(b.date, a.date) = 1)/(select sum(if(date=dt, 1, 0)) as cnt from
(select user_id, date, min(date) over (partition by user_id) as dt from login) s), 3) as p
;
select date, sum(if(date=mind, 1, 0)) as new from
(select user_id, date, min(date) over (partition by user_id) as mind from login) s
group by date order by date;
-- 每个日期"新用户"的留存率
select date, round(ifnull(a.cnt/b.new, 0), 3) as p from (select a.date, count(*) as cnt from login a join login b on a.user_id = b.user_id and datediff(b.date, a.date) = 1 where (a.user_id, a.date) in (select user_id, min(date) from login group by user_id) group by a.date) a right join (select date, sum(if(date=mind, 1, 0)) as new from (select date, min(date) over (partition by user_id) as mind from login) s group by date) b using(date) order by date;
select name as u_n, date, sum(number) over (partition by name order by date) as ps_num from
(select distinct name, b.date, number
from login a join passing_number b using(user_id) join user c on a.user_id = c.id) s
order by date, u_n
;
select id, name, score from
(select a.id, name, score, dense_rank() over (partition by name order by score desc) as rk from grade a join language b on a.language_id = b.id) s where rk <= 2
order by name, score desc, id;
select job, ceil(cnt/2) as start, ceil(cnt/2) as end from
(select *, count(*) over (partition by job) as cnt from grade) s
where cnt % 2 = 1
union
select job, ceil(cnt/2) as start, ceil(cnt/2)+1 as end from
(select *, count(*) over (partition by job) as cnt from grade) s
where cnt % 2 = 0
order by job;
select id, job, score, rk as t_rank from
(select *, row_number() over (partition by job order by score desc) rk, count(*) over (partition by job) as cnt from grade) s where cnt % 2 = 1 and rk = ceil(cnt/2)
union
select id, job, score, rk as t_rank from
(select *, row_number() over (partition by job order by score desc) rk, count(*) over (partition by job) as cnt from grade) s where cnt % 2 = 0 and rk between ceil(cnt/2) and ceil(cnt/2)+1
order by id;
select user_id, min(date) as first_buy_date, sum(if(status='completed', 1, 0)) as cnt
from order_info
where date > '2025-10-15' and product_name in ('C++', 'Java', 'Python')
group by user_id having cnt >= 2 order by user_id;
select user_id, max(if(rk=1, date, 0)) as first_buy_date, max(if(rk=2, date, 0)) as second_buy_date,
count(*) as cnt from
(select user_id, product_name, date, status, DENSE_RANK() over (partition by user_id order by date) as rk
from order_info where date > '2025-10-15' and product_name in ('C++', 'Java', 'Python') and status = 'completed') s group by user_id having cnt >= 2 order by user_id
;
解法一
# select a.id, is_group_buy, b.name as client_name
# from order_info a left join client b on a.client_id = b.id
# where a.user_id in (select user_id from order_info
# where date > '2025-10-15' and product_name in ('C++', 'Java', 'Python')
# group by user_id having sum(if(status='completed', 1, 0)) >= 2) and date > '2025-10-15'
# and product_name in ('C++', 'Java', 'Python') and status = 'completed'
# order by a.id;
解法二
select id, is_group_buy, client_name from
(select a.id, is_group_buy, b.name as client_name,
count(*) over (partition by user_id) as cnt from
order_info a left join client b on a.client_id = b.id
where date > '2025-10-15' and product_name in ('C++', 'Java', 'Python') and status = 'completed') s
where cnt >= 2 order by id;
select source, count(*) as cnt from
(select ifnull(b.name, 'GroupBuy') as source, a.is_group_buy, count(*) over (partition by user_id) as cnt
from order_info a left join client b on a.client_id = b.id
where date > '2025-10-15' and product_name in ('C++', 'Java', 'Python') and status = 'completed') s
where cnt >= 2 group by source order by source;
with t as (
select distinct job, date_format(date, '%Y-%m') as dt, sum(num) over (partition by job, date_format(date, '%Y-%m')) as num from resume_info where year(date) in (2025, 2026)
)
select a.job, first_year_mon, first_year_cnt, second_year_mon, second_year_cnt from
(select job, dt as first_year_mon, num as first_year_cnt from t where left(dt, 4)=2025) a
join (select job, dt as second_year_mon, num as second_year_cnt from t where left(dt, 4)=2026) b
on a.job = b.job and right(first_year_mon, 2) = right(second_year_mon, 2) order by first_year_mon desc, job desc
;
with t as (select grade, sum(number) over (order by grade) as place, (select sum(number) from class_grade) as total from class_grade)
select grade from t where place between ceil(total/2) and total-1 and total % 2 = 0
union
select min(grade) as grade from t where place between ceil(total/2) and total-1 and total % 2 = 1
having grade is not null;
select id, name, grade_num from
(select *, dense_rank() over (order by grade_num desc) as rk from
(select distinct user_id as id, name, sum(grade_num) over (partition by user_id) as grade_num
from grade_info a join user b on a.user_id = b.id) s) s1 where rk = 1 order by id;
select id, name, grade_num from
(select user_id as id, name, sum(if(type='add', grade_num, -grade_num)) as grade_num, dense_rank() over (order by sum(if(type='add', grade_num, -grade_num)) desc) as rk
from grade_info a join user b on a.user_id = b.id group by user_id, name) s where rk = 1 order by id;
select music_name
from music
where id not in (select music_id from music_likes where user_id = 1)
and id in (select music_id from music_likes where user_id in (select follower_id from follow where user_id = 1)) order by id;