Question

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
Was it helpful?

Solution

You can use the ROW_NUMBER function to return only the "best" row per subject:

SQL Fiddle

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

Results:

| NAME | SUBJECT | MARKS |
--------------------------
|    f |       C |    46 |
|    g |       H |    20 |
|    c |       M |    30 |

OTHER TIPS

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;

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

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>

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

enter image description here

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;

The below query will work perfectly:

select subject_name,student_name from student
inner join mark m using(student_id)
inner join subject su using(subject_id)
inner join (select subject_id,max(value) as maximum from mark m group by subject_id)
highestmark using(subject_id) where highestmark.maximum = m.value
order by subject_name,student_name;

This query will work

select name,subject,marks from stud where marks in (select max(marks) from stud      group by subject) ;

SELECT Max(Name) as Name, Subject, Max(Marks) as Marks
FROM Student
group by Subject

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top