这个查询使用了 IF
函数来处理 exam_record
表中的数据。IF
函数在这里用来决定当某些条件满足时应该返回什么值。下面是这个查询的逐行解释:
- 子查询:
-
SELECT er.uid, ...
这一行指定了子查询选择哪些字段。 IF (er.submit_time IS NOT NULL, TIMESTAMPDIFF(MINUTE, start_time, submit_time), ef.duration) AS time_diff
: 这个表达式检查submit_time
是否为NULL
。
- 如果
submit_time
不是NULL
,则使用TIMESTAMPDIFF
函数计算考试开始时间 (start_time
) 到提交时间 (submit_time
) 的分钟数。 - 如果
submit_time
是NULL
,则使用ef.duration
作为考试持续时间。
IF (er.submit_time IS NOT NULL, er.score, 0) AS new_score
: 这个表达式检查submit_time
是否为NULL
。
- 如果
submit_time
不是NULL
,则使用er.score
作为分数。 - 如果
submit_time
是NULL
,则使用0
作为分数。
- 外部查询:
-
SELECT UID, round(avg(new_score)) AS avg_score, round(avg(time_diff), 1) AS avg_time_took
: 这一行指定了外部查询选择哪些字段。 -
FROM ( ... ) t
: 这里使用了之前定义的子查询结果,并将其命名为t
。 -
GROUP BY UID
: 按照UID
对结果进行分组。 -
ORDER BY UID
: 按照UID
对最终结果进行排序。
整体解释
这个查询的目标是从 exam_record
表中获取每个用户的平均分数和平均完成时间,但只针对那些难度为 “hard” 的考试,并且用户级别为 0 的用户。
- 首先,它从
exam_record
表中选择了用户 ID (uid
),并使用IF
函数来确定完成时间 (time_diff
) 和分数 (new_score
)。 - 对于完成时间,如果考试被提交了,则计算提交时间与开始时间之间的差值;如果没有提交,则使用
duration
字段。 - 对于分数,如果考试被提交了,则使用实际的分数;如果没有提交,则分数为
0
。 - 接着,外部查询对子查询的结果进行分组和聚合,计算每个用户的平均分数和平均完成时间。
- 最后,按照
UID
对结果进行排序。
这样,查询就生成了一个列表,列出了每个用户的平均分数和平均完成时间,特别关注的是那些完成了难度为 “hard” 的考试的用户。