回答率最高的问题:条件计数再相除
LeetCode 578 · 条件聚合、比率排序
面试怎么回答
按 question_id 分组,用 SUM(action = 'answer') / SUM(action = 'show') 算回答率,降序取第一。我会补上 question_id 作为第二排序键保证结果确定,并留意展示为 0 时比值为 NULL 的情况。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
问卷日志记录了每个问题被展示(show)、回答(answer)、跳过(skip)的行为。回答率 = 回答次数 / 展示次数,找出回答率最高的问题 ID。
表结构
- survey_log:id(用户)、action(show / answer / skip)、question_id、answer_id、q_num、timestamp
思路
按问题分组,用条件求和分别数出 answer 和 show 的次数,相除后降序取第一。可以先在子查询里算好两个计数再排序,也可以直接在 ORDER BY 里写比值表达式。
参考解法
写法 1:子查询里先算回答数和展示数
select question_id survey_log
from (
select
question_id,
sum(if(action = 'answer', 1, 0)) as AnswerCnt,
sum(if(action = 'show', 1, 0)) as ShowCnt
from
survey_log
group by question_id
) as tbl
order by (AnswerCnt / ShowCnt) desc
limit 1
写法 2:直接在 ORDER BY 里用比值
select question_id survey_log
from survey_log
group by question_id
order by sum(if(action = 'answer', 1, 0)) / sum(if(action = 'show', 1, 0)) desc
limit 1
易错点
- 展示次数为 0 时除法得到 NULL,降序时 NULL 的位置因数据库而异(MySQL 里 NULL 排在最后),要心里有数。
- 回答率相同的多个问题,题目通常要求取 question_id 最小的,可以在排序里补 question_id。