列表

详情


SQL134. 满足条件的用户的试卷完成数和题目练习数

描述

现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间):
id uid nick_name achievement level job register_time
1 1001
牛客1号
3100
7 算法
2020-01-01 10:00:00
2 1002
牛客2号
2300
7 算法
2020-01-01 10:00:00
3 1003
牛客3号
2500
7 算法
2020-01-01 10:00:00
4 1004
牛客4号
1200 5 算法
2020-01-01 10:00:00
5 1005 牛客5号
1600
6 C++
2020-01-01 10:00:00
6 1006 牛客6号
2000
6 C++ 2020-01-01 10:00:00

试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间):
id exam_id tag difficulty duration
release_time
1 9001 SQL hard 60 2021-09-01 06:00:00
2 9002 C++ hard
60
2021-09-01 06:00:00
3 9003
算法
medium
80
2021-09-01 10:00:00

试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分):
id uid exam_id start_time submit_time score
1 1001 9001
2021-09-01 09:01:01
2021-09-01 09:31:00 81
2 1002
9002
2021-09-01 12:01:01
2021-09-01 12:31:01 81
3 1003
9001
2021-09-01 19:01:01
2021-09-01 19:40:01 86
4 1003
9002
2021-09-01 12:01:01
2021-09-01 12:31:51 89
5 1004
9001
2021-09-01 19:01:01
2021-09-01 19:30:01
85
6
1005
9002
2021-09-01 12:01:01
2021-09-01 12:31:02
85
7
1006
9003
2021-09-07 10:01:01
2021-09-07 10:21:01
84
8 1006
9001
2021-09-07 10:01:01
2021-09-07 10:21:01
80

题目练习记录表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分):
id uid question_id submit_time score
1 1001 8001 2021-08-02 11:41:01 60
2 1002 8001
2021-09-02 19:30:01 50
3 1002 8001
2021-09-02 19:20:01
70
4 1002 8002 2021-09-02 19:38:01
70
5 1004 8001
2021-08-02 19:38:01
70
6 1004
8002 2021-08-02 19:48:01
90
7 1001 8002
2021-08-02 19:38:01
70
8 1004 8002
2021-08-02 19:48:01
90
9 1004
8002
2021-08-02 19:58:01
94
10 1004
8003
2021-08-02 19:38:01
70
11 1004
8003
2021-08-02 19:48:01
90
12 1004
8003
2021-08-01 19:38:01
80
请你找到高难度SQL试卷得分平均值大于80并且是7级的红名大佬,统计他们的2021年试卷总完成次数和题目总练习次数,只保留2021年有试卷完成记录的用户。结果按试卷完成数升序,按题目练习数降序。
示例数据输出如下:
uid exam_cnt question_cnt
1001 1 2
1003 2 0

解释:用户1001、1003、1004、1006满足高难度SQL试卷得分平均值大于80,但只有1001、1003是7级红名大佬;1001完成了1次试卷1001,练习了2次题目;1003完成了2次试卷9001、9002,未练习题目(因此计数为0)

示例1

输入:

drop table if exists examination_info,user_info,exam_record,practice_record;
CREATE TABLE examination_info (
    id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
    tag varchar(32) COMMENT '类别标签',
    difficulty varchar(8) COMMENT '难度',
    duration int NOT NULL COMMENT '时长',
    release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE user_info (
    id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    uid int UNIQUE NOT NULL COMMENT '用户ID',
    `nick_name` varchar(64) COMMENT '昵称',
    achievement int COMMENT '成就值',
    level int COMMENT '用户等级',
    job varchar(32) COMMENT '职业方向',
    register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE practice_record (
    id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    uid int NOT NULL COMMENT '用户ID',
    question_id int NOT NULL COMMENT '题目ID',
    submit_time datetime COMMENT '提交时间',
    score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE exam_record (
    id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
    uid int NOT NULL COMMENT '用户ID',
    exam_id int NOT NULL COMMENT '试卷ID',
    start_time datetime NOT NULL COMMENT '开始时间',
    submit_time datetime COMMENT '提交时间',
    score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
  (1001, '牛客1号', 3100, 7, '算法', '2020-01-01 10:00:00'),
  (1002, '牛客2号', 2300, 7, '算法', '2020-01-01 10:00:00'),
  (1003, '牛客3号', 2500, 7, '算法', '2020-01-01 10:00:00'),
  (1004, '牛客4号', 1200, 5, '算法', '2020-01-01 10:00:00'),
  (1005, '牛客5号', 1600, 6, 'C++', '2020-01-01 10:00:00'),
  (1006, '牛客6号', 2000, 6, 'C++', '2020-01-01 10:00:00');

INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
  (9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
  (9002, 'C++', 'hard', 60, '2021-09-01 06:00:00'),
  (9003, '算法', 'medium', 80, '2021-09-01 10:00:00');

INSERT INTO practice_record(uid,question_id,submit_time,score) VALUES
(1001, 8001, '2021-08-02 11:41:01', 60),
(1002, 8001, '2021-09-02 19:30:01', 50),
(1002, 8001, '2021-09-02 19:20:01', 70),
(1002, 8002, '2021-09-02 19:38:01', 70),
(1004, 8001, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1001, 8002, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1004, 8002, '2021-08-02 19:58:01', 94),
(1004, 8003, '2021-08-02 19:38:01', 70),
(1004, 8003, '2021-08-02 19:48:01', 90),
(1004, 8003, '2021-08-01 19:38:01', 80);

INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1003, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 86),
(1003, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:51', 89),
(1004, 9001, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:02', 85),
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 84),
(1006, 9001, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 80);

输出:

1001|1|2
1003|2|0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Mysql 解法, 执行用时: 37ms, 内存消耗: 6380KB, 提交时间: 2022-01-27

select er1.uid as uid,
       count(distinct er1.exam_id) as exam_cnt,
       count(distinct pr1.id) as question_cnt
from exam_record er1
left join practice_record pr1 on er1.uid = pr1.uid and year(er1.submit_time)=2021  and YEAR(pr1.submit_time)=2021
where er1.uid in (
    select er.uid
from user_info ui
left join exam_record er on ui.uid = er.uid
join examination_info ei on er.exam_id = ei.exam_id
where  ei.tag = 'SQL' and ui.level = 7 and difficulty = 'hard' and year(submit_time)=2021
group by ui.uid
having avg(er.score) >80)
group by er1.uid
order by exam_cnt , question_cnt desc;

Mysql 解法, 执行用时: 37ms, 内存消耗: 6396KB, 提交时间: 2021-12-02

with info as(
select DISTINCT uid
    from examination_info inner join exam_record using(exam_id)
    inner  join user_info using (uid)
    where difficulty='hard'
        and tag='SQL'
        and submit_time is not NULL
        and level=7
        group by uid
        having avg(score)>80
)
select DISTINCT user_info.uid,
    count(distinct exam_record.exam_id)as exam_cnt,
    count(distinct practice_record.submit_time)as question_cnt
    from user_info left outer join exam_record 
    on(user_info.uid=exam_record.uid 
       and extract(year from exam_record.submit_time)=2021)
    left outer  join practice_record 
    on(user_info.uid=practice_record.uid
      and extract(year from practice_record.submit_time)=2021)
    where  user_info.uid in (select * from info)
    group by user_info.uid
    order by exam_cnt,user_info.uid desc

Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2022-01-27

SELECT
d.uid
,count(distinct case  when substr(d.submit_time,1,4)='2021' then d.id else null  end ) exam_cnt
,count(distinct case  when substr(e.submit_time,1,4)='2021' then e.id else null  end ) question_cnt 
from
exam_record d left join
practice_record e
on d.uid=e.uid
where d.uid in
(
select
a.uid
from
user_info  a join  exam_record b
on a.uid=b.uid
join examination_info c
on c.exam_id=b.exam_id
where c.tag='sql' and c.difficulty='hard'
and a.level>='7'and substr(submit_time,1,4)='2021'
group by  a.uid
having avg(b.score)>='80') and  substr(d.submit_time,1,4)='2021'
group by d.uid
order by exam_cnt,question_cnt desc;

Mysql 解法, 执行用时: 37ms, 内存消耗: 6400KB, 提交时间: 2021-11-30

with target_user as
(#先是筛选特定的用户
select 
b.uid,
avg(b.score)
from examination_info a 
left join exam_record b on a.exam_id=b.exam_id
inner join user_info c on b.uid=c.uid and c.level=7
where a.tag='SQL' and a.difficulty='hard' 
group by b.uid
having avg(b.score)>=80
)

#接下来连接三个表,因为exam_record和practice_record 的主键是id,
#所以计算次数时可以用dsitinct id
select 
c.uid,
count(distinct a.id) as exam_cnt,
count(distinct b.id) as question_cnt
from target_user c
left join exam_record a on a.uid =c.uid and year(a.submit_time)=2021 
left join practice_record b on b.uid=c.uid and year(b.submit_time)=2021
group by c.uid
order by exam_cnt,question_cnt desc

Mysql 解法, 执行用时: 37ms, 内存消耗: 6404KB, 提交时间: 2022-01-22

select 
t1.uid,
-- count(distinct case when year(t2.submit_time) = '2021' then t2.exam_id else null end) as exam_cnt, -- 不对
-- count(distinct case when year(t3.submit_time) = '2021' then t3.question_id else null end) as question_cnt -- 不对
count(distinct case when year(t2.submit_time) = '2021' then t2.id else null end) as exam_cnt, -- 正确	
count(distinct case when year(t3.submit_time) = '2021' then t3.id else null end) as question_cnt -- 正确
from 
(
	select A.uid
	from exam_record AS A
    INNER JOIN user_info AS B
    ON A.uid = B.uid 
    INNER JOIN examination_info AS C
    ON A.exam_id = C.exam_id
    where B.level  = 7 
	      and 
          C.tag = 'SQL' 
          and 
          C.difficulty = 'hard'
	group by uid 
	having avg(score) > 80 
) t1 
 -- join -- 不能用join
left join 
exam_record t2 
on t1.uid = t2.uid 
 -- join -- 不能用join
left join 
practice_record t3 
on t1.uid = t3.uid 
-- where year(t2.submit_time) = '2021' and  year(t3.submit_time) = '2021' -- 不能在这里统一用where卡条件!!
group by t1.uid
order by exam_cnt asc , question_cnt desc ;
-- 结果按试卷完成数升序,按题目练习数降序