Reputation: 1443
Suppose i have a table as follows:
Class | Subject | Student | Marks
----------------------------------------
1 | Maths | A | 70
1 | Eng | B | 80
1 | IT | A | 90
1 | IT | C | 80
2 | Maths | D | 60
2 | Eng | E | 75
2 | Maths | E | 90
2 | IT | F | 80
3 | Maths | A | 160
3 | Eng | B | 165
3 | IT | G | 90
I want the output as
Class | Student | Marks
----------------------------------------
1 | A | 160
2 | E | 165
3 | B | 165
i.e. Result contains class wise, student name who has max aggregate of marks. How to write a SQL query for this? e.g. for class 1, student A has 70+90 = 160, which becomes maximum over B and C both with 80.
Upvotes: 2
Views: 11732
Reputation: 31
SQL> with cte as
2 (select class, student, sum(marks) marks
3 from engineer
4 group by class, student
5 order by class)
6 select class, student, marks
7 from (select class, student, marks, dense_rank() over(partition by class order by marks desc) rank
8 from cte)
9 where rank=1;
CLASS S MARKS
---------- - ----------
1 A 160
2 E 165
3 B 165
SQL>
Here the most important inner query is for cte table. Resulr set created for this one will be as below.
SQL> select class, student, sum(marks)
2 from engineer
3 group by class, student
4 order by class;
CLASS S SUM(MARKS)
---------- - ----------
1 A 160
1 B 80
1 C 80
2 D 60
2 E 165
2 F 80
3 A 160
3 B 165
3 G 90
9 rows selected.
Upvotes: -1
Reputation: 238076
One solution is to calculate the maximum points a student has per class, and use that as a filtering join:
select ClassStudentSum.*
from (
select class
, student
, sum(Marks) as SumMarks
from YourTable
group by
class
, student
) as ClassStudentSum
join (
select class
, max(SumMarks) as MaxSumMarks
from (
select class
, student
, sum(Marks) as SumMarks
from YourTable
group by
class
, student
) ClassStudentSum2
group by
class
) MaxPerClass
on MaxPerClass.class = ClassStudentSum.class
and MaxPerClass.MaxSumMarks = ClassStudentSum.SumMarks
Upvotes: 5
Reputation: 41
Here is a simpler query, I guess. It works fine. No need of joins.
SELECT class,
(
SELECT student FROM yourtable
WHERE class = YT.class GROUP BY student
ORDER BY SUM(marks) DESC
LIMIT 1
) AS student,
(
SELECT SUM(marks) FROM yourtable
WHERE class = YT.class GROUP BY student
ORDER BY SUM(marks) DESC
LIMIT 1
) AS marks
FROM yourtable AS YT
GROUP BY class
Upvotes: 0
Reputation: 11
The correct query is:
select class, student, sums.mark
from (select class, student, sum(marks) as mark
from student
group by class, student
order by mark desc) sums
group by class
Upvotes: 1
Reputation: 33945
A more traditional (and so slower) approach...
SELECT x.*
FROM
( SELECT class
, student
, SUM(marks) ttl_marks
FROM yourtable
GROUP
BY class
, student
) x
LEFT
JOIN
( SELECT class
, student
, SUM(marks) ttl_marks
FROM yourtable
GROUP
BY class
, student
) y
ON y.class = x.class
AND y.ttl_marks > x.ttl_marks
WHERE y.class IS NULL;
Upvotes: 2
Reputation: 990
Use this Statement.it is works
select Class,Student,Marks
from(
select Class,Student,Marks,Dense_rank() over( partition by class order by marks desc) Rank
from(Select Class, Student,Max(Marks) Marks
from(select Class, Student,Sum(Marks) Marks from Temp14
group by Class,Student
order by 1)
group by Class, Student
order by 1)
)
where Rank=1
Try this one.
Upvotes: 0
Reputation: 8553
Try this query
Query 1:
select a.*, if(@prv=class, 1, 0) as flag, @prv:=class from
(select class,student, sum(marks) as total from table1
group by class, student
order by class, total desc)a join (select @prv:=0)tmp
where if(@prv=class, 1, 0) = 0
| CLASS | STUDENT | TOTAL | FLAG | @PRV:=CLASS |
------------------------------------------------
| 1 | A | 160 | 0 | 1 |
| 2 | E | 165 | 0 | 2 |
| 3 | B | 165 | 0 | 3 |
Hope this helps
Upvotes: 1