明确题意:
当有0级用户未完成试卷数大于2时输出每个0级用户的试卷未完成数和未完成率(保留3位小数); 若不存在这样的用户,则输出所有有作答记录的用户的这两个指标。
结果按未完成率升序排序。
问题分解:
- 统计每个用户的等级、未完成数、未完成率和总作答数,生成临时表 t_tag_count:
- 右连接试卷作答表和用户信息表:exam_record RIGHT JOIN user_info USING(uid)
- 按用户分组:GROUP BY uid
- 统计未完成数:COUNT(start_time) - COUNT(submit_time) as incomplete_cnt
- 统计未完成率:IFNULL(1 - COUNT(submit_time) / COUNT(start_time), 0) as incomplete_rate
- 保留3位小数:ROUND(x, 3)
- 统计总作答数:COUNT(start_time) as total_cnt
- 当存在0级用户未完成试卷数大于2时:
- 筛选存在性条件:WHERE EXISTS (SELECT uid FROM t_tag_count WHERE
level
= 0 AND incomplete_cnt > 2) - 输出每个0级用户的试卷未完成数和未完成率:
- 筛选0级用户:
level
= 0 - SELECT uid, incomplete_cnt, incomplete_rate
- 筛选0级用户:
- 筛选存在性条件:WHERE EXISTS (SELECT uid FROM t_tag_count WHERE
- 当不存在0级用户未完成试卷数大于2时:
- 筛选存在性条件:WHERE NOT EXISTS (SELECT uid FROM t_tag_count WHERE
level
= 0 AND incomplete_cnt > 2) - 输出所有有作答记录的用户的这两个指标:
- 筛选有作答记录的用户:total_cnt > 0
- SELECT uid, incomplete_cnt, incomplete_rate
- 筛选存在性条件:WHERE NOT EXISTS (SELECT uid FROM t_tag_count WHERE
- 合并上述结果,条件互斥,so只可能有一个结果集:UNION ALL
细节问题:
- 表头重命名:as
- 按未完成率升序排序:ORDER BY incomplete_rate
完整代码:
WITH t_tag_count as (
SELECT uid, `level`,
COUNT(start_time) - COUNT(submit_time) as incomplete_cnt, -- 未完成数
ROUND(
IFNULL(1 - COUNT(submit_time) / COUNT(start_time), 0),
3) as incomplete_rate, -- 此人未完成率
COUNT(start_time) as total_cnt -- 总作答数
FROM exam_record
RIGHT JOIN user_info USING(uid)
GROUP BY uid
)
SELECT uid, incomplete_cnt, incomplete_rate
FROM t_tag_count
WHERE EXISTS (
SELECT uid FROM t_tag_count WHERE `level` = 0 AND incomplete_cnt > 2
) AND `level` = 0
UNION ALL
SELECT uid, incomplete_cnt, incomplete_rate
FROM t_tag_count
WHERE NOT EXISTS (
SELECT uid FROM t_tag_count WHERE `level` = 0 AND incomplete_cnt > 2
) AND total_cnt > 0
ORDER BY incomplete_rate;