返回介绍

合并查询

发布于 2024-08-17 15:49:00 字数 7549 浏览 0 评论 0 收藏 0

每个题目和每份试卷被作答的人数和次数

描述

现有试卷作答记录表 exam_record(uid 用户 ID, exam_id 试卷 ID, start_time 开始作答时间, submit_time 交卷时间, score 得分):

iduidexam_idstart_timesubmit_timescore
1100190012021-09-01 09:01:012021-09-01 09:41:0181
2100290022021-09-01 12:01:012021-09-01 12:31:0170
3100290012021-09-01 19:01:012021-09-01 19:40:0180
4100290022021-09-01 12:01:012021-09-01 12:31:0170
5100490012021-09-01 19:01:012021-09-01 19:40:0185
6100290022021-09-01 12:01:01(NULL)(NULL)

题目练习表 practice_record(uid 用户 ID, question_id 题目 ID, submit_time 提交时间, score 得分):

iduidquestion_idsubmit_timescore
1100180012021-08-02 11:41:0160
2100280012021-09-02 19:30:0150
3100280012021-09-02 19:20:0170
4100280022021-09-02 19:38:0170
5100380012021-08-02 19:38:0170
6100380012021-08-02 19:48:0190
7100380022021-08-01 19:38:0180

请统计每个题目和每份试卷被作答的人数和次数,分别按照"试卷"和"题目"的 uv & pv 降序显示,示例数据结果输出如下:

tiduvpv
900133
900213
800135
800222

解释 :“试卷”有 3 人共练习 3 次试卷 9001,1 人作答 3 次 9002;“刷题”有 3 人刷 5 次 8001,有 2 人刷 2 次 8002

思路 :这题的难点和易错点在于 UNOINORDER BY 同时使用的问题

有以下几种情况:使用 union 和多个 order by 不加括号,报错!

order byunion 连接的子句中不起作用;

比如不加括号:

SELECT exam_id AS tid,
       COUNT(DISTINCT UID) AS uv,
       COUNT(UID) AS pv
FROM exam_record
GROUP BY exam_id
ORDER BY uv DESC,
         pv DESC
UNION
SELECT question_id AS tid,
       COUNT(DISTINCT UID) AS uv,
       COUNT(UID) AS pv
FROM practice_record
GROUP BY question_id
ORDER BY uv DESC,
         pv DESC

直接报语法错误,如果没有括号,只能有一个 order by

还有一种 order by 不起作用的情况,但是能在子句的子句中起作用,这里的解决方案就是在外面再套一层查询。

答案

SELECT *
FROM
  (SELECT exam_id AS tid,
          COUNT(DISTINCT exam_record.uid) uv,
          COUNT(*) pv
   FROM exam_record
   GROUP BY exam_id
   ORDER BY uv DESC, pv DESC) t1
UNION
SELECT *
FROM
  (SELECT question_id AS tid,
          COUNT(DISTINCT practice_record.uid) uv,
          COUNT(*) pv
   FROM practice_record
   GROUP BY question_id
   ORDER BY uv DESC, pv DESC) t2;

分别满足两个活动的人

描述 : 为了促进更多用户在牛客平台学习和刷题进步,我们会经常给一些既活跃又表现不错的用户发放福利。假使以前我们有两拨运营活动,分别给每次试卷得分都能到 85 分的人(activity1)、至少有一次用了一半时间就完成高难度试卷且分数大于 80 的人(activity2)发了福利券。

现在,需要你一次性将这两个活动满足的人筛选出来,交给运营同学。请写出一个 SQL 实现:输出 2021 年里,所有每次试卷得分都能到 85 分的人以及至少有一次用了一半时间就完成高难度试卷且分数大于 80 的人的 id 和活动号,按用户 ID 排序输出。

现有试卷信息表 examination_infoexam_id 试卷 ID, tag 试卷类别, difficulty 试卷难度, duration 考试时长, release_time 发布时间):

idexam_idtagdifficultydurationrelease_time
19001SQLhard602021-09-01 06:00:00
29002C++easy602021-09-01 06:00:00
39003算法medium802021-09-01 10:00:00

试卷作答记录表 exam_recorduid 用户 ID, exam_id 试卷 ID, start_time 开始作答时间, submit_time 交卷时间, score 得分):

iduidexam_idstart_timesubmit_timescore
1100190012021-09-01 09:01:012021-09-01 09:31:0081
2100290022021-09-01 12:01:012021-09-01 12:31:0170
3100390012021-09-01 19:01:012021-09-01 19:40:0186
4100390022021-09-01 12:01:012021-09-01 12:31:0189
5100490012021-09-01 19:01:012021-09-01 19:30:0185

示例数据输出结果:

uidactivity
1001activity2
1003activity1
1004activity1
1004activity2

解释 :用户 1001 最小分数 81 不满足活动 1,但 29 分 59 秒完成了 60 分钟长的试卷得分 81,满足活动 2;1003 最小分数 86 满足活动 1,完成时长都大于试卷时长的一半,不满足活动 2;用户 1004 刚好用了一半时间(30 分钟整)完成了试卷得分 85,满足活动 1 和活动 2。

思路 : 这一题需要涉及到时间的减法,需要用到 TIMESTAMPDIFF() 函数计算两个时间戳之间的分钟差值。

下面我们来看一下基本用法

示例:

TIMESTAMPDIFF(MINUTE, start_time, end_time)

TIMESTAMPDIFF() 函数的第一个参数是时间单位,这里我们选择 MINUTE 表示返回分钟差值。第二个参数是较早的时间戳,第三个参数是较晚的时间戳。函数会返回它们之间的分钟差值

了解了这个函数的用法之后,我们再回过头来看 activity1 的要求,求分数大于 85 即可,那我们还是先把这个写出来,后续思路就会清晰很多

SELECT DISTINCT UID
FROM exam_record
WHERE score >= 85
  AND YEAR (start_time) = '2021'

根据条件 2,接着写出 在一半时间内完成高难度试卷且分数大于 80 的人

SELECT UID
FROM examination_info info
INNER JOIN exam_record record
WHERE info.exam_id = record.exam_id
  AND (TIMESTAMPDIFF(MINUTE, start_time, submit_time)) < (info.duration / 2)
  AND difficulty = 'hard'
  AND score >= 80

然后再把两者 UNION 起来即可。(这里特别要注意括号问题和 order by 位置,具体用法在上一篇中已提及)

答案

SELECT DISTINCT UID UID,
                    'activity1' activity
FROM exam_record
WHERE UID not in
    (SELECT UID
     FROM exam_record
     WHERE score<85
       AND YEAR(submit_time) = 2021 )
UNION
SELECT DISTINCT UID UID,
                    'activity2' activity
FROM exam_record e_r
LEFT JOIN examination_info e_i ON e_r.exam_id = e_i.exam_id
WHERE YEAR(submit_time) = 2021
  AND difficulty = 'hard'
  AND TIMESTAMPDIFF(SECOND, start_time, submit_time) <= duration *30
  AND score>80
ORDER BY UID

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文