题目描述
(通过次数16,880 | 提交次数38,443,通过率43.91%)
SurveyLog 表: +-------------+------+ | Column Name | Type | +-------------+------+ | id | int | | action | ENUM | | question_id | int | | answer_id | int | | q_num | int | | timestamp | int | +-------------+------+ 这张表没有主键,其中可能包含重复项。 action 是一个 ENUM 数据,可以是 "show"、"answer" 或者 "skip" 。 这张表的每一行表示:ID = id 的用户对 question_id 的问题在 timestamp 时间进行了 action 操作。 如果用户对应的操作是 "answer" ,answer_id 将会是对应答案的 id ,否则,值为 null 。 q_num 是该问题在当前会话中的数字顺序。 回答率 是指:同一问题编号中回答次数占显示次数的比率。 编写一个 SQL 查询以报告 回答率 最高的问题。如果有多个问题具有相同的最大 回答率 ,返回 question_id 最小的那个。 查询结果如下例所示。 示例: 输入: SurveyLog table: +----+--------+-------------+-----------+-------+-----------+ | id | action | question_id | answer_id | q_num | timestamp | +----+--------+-------------+-----------+-------+-----------+ | 5 | show | 285 | null | 1 | 123 | | 5 | answer | 285 | 124124 | 1 | 124 | | 5 | show | 369 | null | 2 | 125 | | 5 | skip | 369 | null | 2 | 126 | +----+--------+-------------+-----------+-------+-----------+ 输出: +------------+ | survey_log | +------------+ | 285 | +------------+ 解释: 问题 285 显示 1 次、回答 1 次。回答率为 1.0 。 问题 369 显示 1 次、回答 0 次。回答率为 0.0 。 问题 285 回答率最高。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/get-highest-answer-rate-question
//测试数据 Create table If Not Exists SurveyLog (id int, action varchar(255), question_id int, answer_id int, q_num int, timestamp int); insert into SurveyLog (id, action, question_id, answer_id, q_num, timestamp) values ('5', 'show', '285', 'None', '1', '123'); insert into SurveyLog (id, action, question_id, answer_id, q_num, timestamp) values ('5', 'answer', '285', '124124', '1', '124'); insert into SurveyLog (id, action, question_id, answer_id, q_num, timestamp) values ('5', 'show', '369', 'None', '2', '125'); insert into SurveyLog (id, action, question_id, answer_id, q_num, timestamp) values ('5', 'skip', '369', 'None', '2', '126');
解题思路
这道题从解题步骤上来说并不难。
**第一步**:计算出每个问题的show次数;
限制action=’show’,再根据问题ID分组统计;
**第二步**:计算出每个问题的answer次数;
限制action=’answer’,再根据问题ID分组统计;
**第三步**:计算出每个问题的回答率(answer次数 / show次数);
第一步与第二步的结果合并,answer次数 / show次数得出回答率;
**第四步**:按回答率排序,取出回答率最大的问题。如果有多个问题回答率相同,取问题ID最小的那个;
使用order by排序,再取出第一行即可。
上面每一步实现起来都比较简单,但如何能简洁的实现是难点。
第一、二步,都是以问题ID分组统计,是不是可以一次性计算出来呢?
实际上,可以使用如下语句来实现:在汇总时根据action的值决定是否计算数量。
select a.question_id, sum(case when action = 'answer' then 1 else 0 end), sum(case when action = 'show' then 1 else 0 end) from SurveyLog a group by a.question_id;
另外,在SELECT语句中,GROUP BY子句先于ORDER BY子句执行,因此,可以在ORDER BY子句中使用SUM聚合函数。
而ORDER BY子句又先于LIMIT子句执行,因此,可以在ORDER BY子句排完序后,使用LIMIT子句限定返回的行数。
如此,一条SELECT查询语句即可得出结果。
当然,使用子查询、窗口函数,也可以实现最终的效果,但都没有直接查询来的简洁。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select a.question_id survey_log from SurveyLog a group by a.question_id order by sum(case when action = 'answer' then 1 else 0 end) / sum(case when action = 'show' then 1 else 0 end) desc, a.question_id limit 1;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。