I have the following table
Name | Subject | Marks
--------------------------
a M 20
b M 25
c M 30
d C 44
e C 45
f C 46
g H 20
Here I have a "Student" table I want to get the Name of the student who got
Max marks from each subject from the student table like the following OUTPUT.
Name | Subject | Marks
c M 30
f c 46
g h 20
You can use the ROW_NUMBER function to return only the "best" row per subject:
MS SQL Server 2008 Schema Setup:
CREATE TABLE Student
([Name] varchar(1), [Subject] varchar(1), [Marks] int)
;
INSERT INTO Student
([Name], [Subject], [Marks])
VALUES
('a', 'M', 20),
('b', 'M', 25),
('c', 'M', 30),
('d', 'C', 44),
('e', 'C', 45),
('f', 'C', 46),
('g', 'H', 20)
;
Query 1:
SELECT Name, Subject, Marks
FROM(
SELECT *, ROW_NUMBER()OVER(PARTITION BY Subject ORDER BY Marks DESC) rn
FROM dbo.Student
)X
WHERE rn = 1
| NAME | SUBJECT | MARKS |
--------------------------
| f | C | 46 |
| g | H | 20 |
| c | M | 30 |
This Basic Query should work for your req.
SELECT Name, Subject, Max(Marks)
FROM Student
GROUP by Subject;
Tried in SQLFiddle
Note: Used SQLite for check
You can use other functions and cte also to get the result..
eg : 1
select B.Name,
A.Subject,
B.Marks
from ( select Subject,
max(Marks) as High_Marks
from Student
group by Subject
) a
join Student b
on a.subject = b.subject
and a.high_Marks = b.Marks
Eg : 2 : use of cte and dense_rank function
;WITH cte
AS
(
SELECT
[Name],
[Subject],
[Marks],
dense_rank() over(partition BY [Subject] order by [Marks] DESC) AS Rank
FROM Student
)
SELECT * FROM cte WHERE Rank = 1;
SQL> with cte as
2 (
3 select name, subject, marks, dense_rank() over (partition by subject order
by marks desc) rnk
4 from student)
5 select name, subject, marks
6 from cte
7 where rnk=1;
N S MARKS
- - ----------
f c 46
c m 30
SQL>
SELECT Max(Name) as Name, Subject, Max(Marks) as MarksFROM Studentgroup by Subject
A Similar problem :
Write a query to display the name(s) of the students who have secured the maximum marks in each subject, ordered by subject name in ascending order.
If there are multiple toppers, display their names in alphabetical order.
Display it as subject_name and student_name.
O/P:
- First column - subject_name
- Second column - student_name
Solution for this problem:
SELECT subject_name,student_name
from Student s
inner join Mark m on s.student_id=m.student_id
inner join Subject su on m.subject_id=su.subject_id
inner join (select subject_id
,max(value) as maximum
from Mark ma group by subject_id
) highmarks
ON highmarks.subject_id=m.subject_id
AND highmarks.maximum=m.value
order by subject_name,student_name;
来源:https://stackoverflow.com/questions/18058170/how-to-get-the-name-of-a-the-student-who-got-max-marks-in-each-subject
