我有一张桌子,其中学生在每个科目中进行标记,我必须以这样的方式获得查询,以便我能够在每个获得最高分的科目中获得所有前5名学生。
以下是一个示例表:
我的预期输出看起来像:
基于学生分数的PCM,ART,PCB的前五名学生,如果两个或更多学生的安全性与那些记录相同,也需要在列表中进行单一查询。
答案 0 :(得分:2)
从技术上讲,使用单个SQL
查询无法实现您想要完成的任务。如果您只想要每个科目一名学生,您可以使用GROUP BY
实现这一目标,但在您的情况下,它将无效。
我能想到让每个主题有5名学生的唯一方法是编写 x
查询,每个主题一个,并使用UNION
将它们粘合在一起。此类查询最多会返回 5x
行。
由于您希望根据该标记获得前5名学生,因此您必须使用ORDER BY
子句,该子句与UNION
子句一起将导致错误。为避免这种情况,您必须使用子查询,以便UNION
和ORDER BY
子句不在同一级别。
<强>查询:强>
-- Select the 5 students with the highest mark in the `PCM` subject.
(
SELECT *
FROM student
WHERE subject = 'PCM'
ORDER BY studentMarks DESC
LIMIT 5
)
UNION
(
SELECT *
FROM student
WHERE subject = 'PCB'
ORDER BY studentMarks DESC
LIMIT 5
)
UNION
(
SELECT *
FROM student
WHERE subject = 'ART'
ORDER BY studentMarks DESC
LIMIT 5
);
查看this SQLFiddle以自行评估结果。
此更新旨在让超过5名学生参与该场景,即许多学生在特定科目中拥有相同的成绩。
我们使用LIMIT 5
来获得排名第五的成绩,而不是使用LIMIT 4,1
来获得排名第五的成绩,并使用它来获得所有等级高于或等于给定成绩的学生学科。但是,如果有&lt;主题LIMIT 4,1
中的5名学生将返回NULL
。在这种情况下,我们基本上需要每个学生,所以我们使用最低成绩。
要实现上述目标,您需要使用以下代码 x
次,与您拥有的主题一样多,并使用{{1}将它们连接在一起}。可以很容易地理解,这个解决方案可以用于少数不同的主题,或者查询的范围将变得不可维护。
<强>代码:强>
UNION
查看this SQLFiddle以自行评估结果。
<强>替代:强>
经过一些研究后,我发现了一个替代的,更简单的查询,它将根据您提供的数据产生与上面提供的相同的结果,而不需要“硬编码”每个主题都在自己的查询。
在下面的解决方案中,我们定义了几个帮助我们控制数据的变量:
<强>查询:强>
-- Select the students with the top 5 highest marks in the `x` subject.
SELECT *
FROM student
WHERE studentMarks >= (
-- If there are less than 5 students in the subject return them all.
IFNULL (
(
-- Get the fifth highest grade.
SELECT studentMarks
FROM student
WHERE subject = 'x'
ORDER BY studentMarks DESC
LIMIT 4,1
), (
-- Get the lowest grade.
SELECT MIN(studentMarks)
FROM student
WHERE subject = 'x'
)
)
) AND subject = 'x';
查看this SQLFiddle以自行评估结果。
以下主题采取了一些想法:
答案 1 :(得分:0)
以下查询几乎可以产生我想要的内容,这个查询可能会在将来帮助其他人。
SELECT a.studentId, a.studentName, a.StudentMarks,a.subject FROM testquery AS a WHERE
(SELECT COUNT(*) FROM testquery AS b
WHERE b.subject = a.subject AND b.StudentMarks >= a.StudentMarks) <= 2
ORDER BY a.subject ASC, a.StudentMarks DESC