0

I have a db that looks like this

+--------+-------+-------+
| ID     | Class | grade |
+--------+-------+-------+
| 123    |   A   | 100   |
| 2      |   B   | 84    |
| 357    |   A   | 46    |
| 43     |   B   | 12    |
| 55677  |   B   | 78    |
| 63432  |   A   | 63    |
+--------+-------+-------+

obviously, I am dealing with much bigger db. more students, and more classes wha I want to achieve is select two students with the highest grades from each class.

So, it should show:

+-------+-------+-------+
| ID    | Class | Grade |
+-------+-------+-------+
| 123   | A     | 100   |
| 63432 | A     | 63    |
| 2     | B     | 84    |
| 55677 | B     | 78    |
+-------+-------+-------+

How do I achieve this thank you!

I tried this, but it gives me all rows

select id, class, max(grade)
from school
group by id, class

++++

There is another thing that I'd like to do with this db. How do I go about pulling top 10% students from each class? After I added a rank attribute, I tried using 'having' after group by like this:

rank < count(distinct ID) * 0.05

Thank you!

Nayana
  • 1,513
  • 3
  • 24
  • 39

4 Answers4

2

Use ROW_NUMBER() function with partition by clause.

;WITH CTE AS (

SELECT id, Class, Grade,
       ROW_NUMBER() OVER(PARTITION BY Class ORDER BY Grade DESC) as rnk
FROM tableName
)

SELECT id, Class, Grade
FROM CTE
WHERE rnk <=2
Mudassir Hasan
  • 28,083
  • 20
  • 99
  • 133
1

for this you need to use group by and having:

    select id,Class,Grade 
    from Student e 
    where Grade=(select max(Grade) 
    from Student w 
    group by w.Class having e.class=w.class)
0

I think, DENSE_RANK is better here than ROW_NUMBER.

Query

;with cte as(
    select [rank] = dense_rank() over(
        partition by [Class]
        order by [grade] desc
    ), *
    from [your_table_name]
)
select * from cte
where [rank] <= 2;
Ullas
  • 11,450
  • 4
  • 33
  • 50
  • how did you line the database the way you did it? I always used a lot of spaces to line the numbers. How did you do + -- | this stuff? It looks a lot better, thank you for editing my question . – Nayana Nov 08 '16 at 09:03
  • Do you know a way to pull top 10% students from each class? thank you! – Nayana Nov 09 '16 at 04:46
0

try this:

WITH result AS (

SELECT Id, Class, Grade,
       dense_rank() OVER(PARTITION BY Class ORDER BY Grade DESC) as DenseRank
FROM tableName
)

SELECT Id, Class, Grade
FROM result
WHERE DenseRank <=2

more than one student with same highest grade will also be considered.

James
  • 729
  • 6
  • 10