这是我的sqlfiddler bech; http://sqlfiddle.com/#!3/9d859
Grades:
SID CID GRADE
--------------
S1 C1 50
S1 C2 85
S1 C3 60
S1 C4 90
S1 C5 50
S2 C1 30
S2 C2 40
S3 C2 85
S4 C2 80
S4 C4 75
S4 C5 60
我们有成绩表, SID = Student_ID CID = Course_ID
我们希望从“C1”课程中获得最高分的学生的SID。
这是我的解决方案
SELECT DISTINCT SID
FROM GRADES
WHERE GRADE =
(SELECT max(GRADE)
FROM GRADES
GROUP BY CID HAVING CID = 'C1')
在我看来这是错误的,我该如何解决?
答案 0 :(得分:1)
您必须过滤相应的课程日期,按年级desc排序并获得第一行。
SELECT
SID
FROM grades
WHERE CID = 'C1'
ORDER BY GRADE DESC
LIMIT 1;
或使用此:
SELECT
SID
FROM grades G1
WHERE CID = 'C1'
AND GRADE = (SELECT MAX(GRADE) FROM grades G2 WHERE G2.CID = G1.CID)
更新
上述查询也适用于SQL Server。
但您也可以使用它:
SELECT TOP 1
SID
FROM grades
WHERE CID = 'C1'
ORDER BY GRADE DESC
如果有多个学生在课程中获得最高分,并且您想要所有这些,则可以使用:
SELECT TOP 1 WITH TIES
SID
FROM grades
WHERE CID = 'C1'
ORDER BY GRADE DESC
FOR Marcus Adams
经过测试:
Microsoft SQL Server 2014 (CTP2) - 12.0.1524.0 (X64) Oct 3 2013 19:00:26 Copyright (c) Microsoft Corporation Enterprise Evaluation Edition (64-bit) on Windows NT 6.2 (Build 9200: )
--SET SHOWPLAN_TEXT ON
SELECT
SID
FROM grades G1
WHERE CID = 'C1'
AND GRADE = (SELECT MAX(GRADE) FROM grades G2 WHERE G2.CID = G1.CID)
(1 row(s) affected) StmtText ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Nested Loops(Inner Join, WHERE:([Expr1002]=[Test].[dbo].[GRADES].[GRADE] as [G1].[GRADE])) |--Stream Aggregate(DEFINE:([Expr1002]=MAX([Test].[dbo].[GRADES].[GRADE] as [G2].[GRADE]))) | |--Clustered Index Scan(OBJECT:([Test].[dbo].[GRADES].[PK__GRADES__4606D4B55925FD88] AS [G2]), WHERE:([Test].[dbo].[GRADES].[CID] as [G2].[CID]='C1')) |--Clustered Index Scan(OBJECT:([Test].[dbo].[GRADES].[PK__GRADES__4606D4B55925FD88] AS [G1]), WHERE:([Test].[dbo].[GRADES].[CID] as [G1].[CID]='C1')) (4 row(s) affected)
--SET SHOWPLAN_TEXT ON
SELECT
SID
FROM grades G1
WHERE CID = 'C1'
AND GRADE = (SELECT MAX(GRADE) FROM grades G2 WHERE G2.CID = 'C1')
(1 row(s) affected) StmtText ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Nested Loops(Inner Join, WHERE:([Expr1002]=[Test].[dbo].[GRADES].[GRADE] as [G1].[GRADE])) |--Stream Aggregate(DEFINE:([Expr1002]=MAX([Test].[dbo].[GRADES].[GRADE] as [G2].[GRADE]))) | |--Clustered Index Scan(OBJECT:([Test].[dbo].[GRADES].[PK__GRADES__4606D4B55925FD88] AS [G2]), WHERE:([Test].[dbo].[GRADES].[CID] as [G2].[CID]='C1')) |--Clustered Index Scan(OBJECT:([Test].[dbo].[GRADES].[PK__GRADES__4606D4B55925FD88] AS [G1]), WHERE:([Test].[dbo].[GRADES].[CID] as [G1].[CID]='C1')) (4 row(s) affected)
答案 1 :(得分:1)
这是错误的,因为您选择的所有学生都与所选课程中的最高成绩相同。 你只想要那些真正完成那门课程的学生。为此,您还需要将课程选择添加到主查询中,而不仅仅是子查询。
你可以这样写:
SELECT DISTINCT
g.SID
FROM
GRADES g
WHERE
g.CID = 'C5' AND
g.GRADE = (SELECT max(g1.GRADE)
FROM GRADES g1
WHERE g1.CID = g.CID)
这将返回所有成绩最高的学生。如果他们获得相同的成绩,这可以是多个学生,但如果您有这样的查询,这似乎是合乎逻辑的。如果你不想那样,你可以使用Hamlet Hakobyan的答案,这将给你一个分享最高分的学生。
注意,我添加DISTINCT
只是因为您的示例中有双重数据。目前,学生S1的成绩是同等最高成绩的两倍,这就是为什么如果你不添加DISTINCT它会出现两次。