我有一个名为Student的sql server表,如下所示:
我希望从每个班级中选出得分最高的学生,这将产生如下输出:
由于某些限制,我无法确定表中会存在多少个唯一的类名。我的存储过程是:
create procedure selectBestStudent
as
begin
select Name, max(TestScore)
from [TestDB1].[dbo].[StudentTest]
group by Name
end
但结果是错误的。有什么想法吗?
答案 0 :(得分:3)
您可以将ROW_NUMBER
与PARTITION BY
:
SELECT Name, Class, TestScore
FROM (
SELECT Name, Class, TestScore,
ROW_NUMBER() OVER (PARTITION BY Class
ORDER BY TestScore DESC) AS rn
FROM StudentTest) AS t
WHERE t.rn = 1
ROW_NUMBER
枚举每个Class
分区中的记录:ORDER BY
子句保证具有最大TestScore
值的记录被赋予等于1的值。
注意:要处理关联,您可以使用RANK
代替ROW_NUMBER
。通过这种方式,您可以为相同的 TestScore
所有学生分享相同的最大 Class
。
答案 1 :(得分:1)
您还可以使用NOT EXISTS()
实现此目标SELECT * FROM Student s
WHERE NOT EXISTS(select 1 FROM Student t
where t.class = s.class
and t.testScore > s.testScore)
这将仅选择那些在testScore上没有具有更高值的行的行
答案 2 :(得分:1)
我认为当一个班级中有多个人具有相同分数时,你会遇到Group By和MAX()的问题。
如果你不知道这是什么,我用fetch解决了它,你可以看here。它比起初看起来更容易!
我知道这可能是一种可怕的方式,但它易于理解且有效! :d
USE [TestDB]
GO
DECLARE @class char(10), @testscore int;
DECLARE @result Table
(
Name char(10),
Class char(10),
TestScore int
);
-- Get Classes and their Maxima
DECLARE TestScore_cursor CURSOR FOR SELECT [class], MAX([testscore]) FROM [student] GROUP BY [class];
OPEN TestScore_cursor;
-- Perform the first fetch.
FETCH NEXT FROM TestScore_cursor INTO @class, @testscore;
-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
-- Search Students by Class and Score and add them to tempTable @result
INSERT INTO @result SELECT [name], [class], [testscore] From [student] where [testScore] = @testscore AND [class] = @class;
FETCH NEXT FROM TestScore_cursor INTO @class, @testscore;
END
-- Show the Result
SELECT * FROM @result;
CLOSE TestScore_cursor;
DEALLOCATE TestScore_cursor;
GO