表结构如下:
Student
(StudentID int,StudentName varchar(20))Subject
(SubjectID int,SubjectName varchar(20))Score
(ScoreID int,StudentID int,SubjectID int,Score int)这是数据
Student
| StudentID | StudentName |
| 1 | John |
| 2 | Nash |
| 3 | Albert |
---------------------------
Subject
| SubjectID | SubjectName |
| 1 | Maths |
| 2 | Physics |
| 3 | Chemistry|
| 4 | English |
---------------------------
Score
| ScoreID | StudentID | SubjectID | Score |
| 1 | 1 | 1 | 34 |
| 2 | 1 | 2 | 45 |
| 3 | 1 | 3 | 56 |
| 4 | 2 | 1 | 78 |
| 5 | 2 | 3 | 23 |
| 6 | 2 | 4 | 44 |
| 7 | 3 | 1 | 45 |
| 8 | 3 | 2 | 10 |
| 9 | 3 | 3 | 54 |
| 10 | 3 | 4 | 74 |
-------------------------------------------
Output:
|StudentName | Score | SubjectName |
| John | 45 | Physics |
| John | 56 | Chemistry |
| Nash | 78 | Maths |
| Albert | 74 | English |
------------------------------------
我想写一个查询来获取每个主题的最佳得分手及其得分和主题名称,而不使用Row_Number(),Rank()和Dense_Rank()。
我写了这个查询,但我认为可以改进:
select
st.StudentName, Score, B.SubjectID
from
(select
StudentID, Sc.SubjectID, Sc.Score
from
(select
SubjectID, MAX(Score) as 'Score'
from
Score Sc
inner join
subject sb on sc.subjectid = sb.subjectid
group by
SubjectID) A
inner join
score sc on sc.SubjectID = a.SubjectID and sc.Score = A.Score) B
inner join
Student st on st.studentID = B.StudentID
答案 0 :(得分:1)
您将使用ANSI标准rank()
或row_number()
函数。假设您想要所有重复项,请使用rank()
:
select StudentName, SubjectName, Score
from (select st.StudentName, su.SubjectName, s.Score,
rank() over (partition by su.SubjectName order by s.Score desc) as seqnum
from score s join
student st
on s.studentid = st.studentid join
subject su
on s.subjectid = su.subjectid
) s
where seqnum = 1;
如果您希望每个主题只有一行,并且有一个任意的优秀学生,请使用row_number()
。
在SQL Server中,您也可以在没有子查询的情况下执行此操作:
select top (1) with ties st.StudentName, su.SubjectName, s.Score
from score s join
student st
on s.studentid = st.studentid join
subject su
on s.subjectid = su.subjectid
order by rank() over (partition by su.SubjectName order by s.Score desc)
另一个有趣的选项是apply
- 这不使用窗口函数,并且可以有相当不错的性能:
select ss.StudentName, su.SubjectName, ss.Score
from subject su cross apply
(select top (1) with ties s.*
from score s join
student st
on s.studentid = st.studentid join
where s.subjectid = su.subjectid
order by su.score desc
) ss;
答案 1 :(得分:1)
这是一个不使用RANK或ROW_NUMBER的解决方案。这也是为了满足您的输出而大大简化的。希望它有所帮助
SELECT st.StudentName ,s.Score ,su.SubjectName FROM (SELECT
SubjectID,MAX(Score) as Max FROM Score GROUP BY SubjectID) a
INNER JOIN Score s on a.SubjectID=s.SubjectID AND a.MAX=s.Score
INNER JOIN Student st on s.StudentID=st.StudentID
INNER JOIN Subject su on s.SubjectID=su.SubjectID