How to aggregate top 5 numbers in SQL Server 2000 - sql

Hi i I am facing a problem, it is that the students can have more than 5 subjects but i have to sum of only 5 subjects total marks of which the student secured the highest. One way to say sum of top 5 total marks obtained by any student.
How do i proceed please help me. Thanks in advance.

In SQL 2000 you will need to use a subselect to determine how many rows with the same ID have a higher mark. Then Filter for rows that have less then 5 higher marked rows above it:
select
ID, Sum(Mark)
From Table1 t
where
(Select count(*)
from Table1 it
where it.id=t.id and it.mark>t.mark) <5
group by ID

ROW_NUMBER isn't in sql-server-2000 unfortunately. You can achieve the same result with a subquery though. Hopefully this is what you're looking for:
SELECT s.studentid, SUM(s.total_marks)
FROM students s
WHERE s.sub_code IN (SELECT TOP 5 sub_code
FROM students a
WHERE a.studentid = s.studentid
ORDER BY total_marks DESC)
GROUP BY studentid
Working in fiddle

Here is a query that gives you only the 5 hightest marks per student:
SELECT studentID, total_marks,
row_number() OVER (PARTITION BY studentID, ORDER BY total_marks DESC) as rowN
FROM studentTable
WHERE rowN <= 5
So to get the total:
SELECT studentID, SUM(total_marks)
FROM
(
SELECT studentID, total_marks,
row_number() OVER (PARTITION BY studentID, ORDER BY total_marks DESC) as rowN
FROM studentTable
WHERE rowN <= 5
) T
GROUP BY studentID

Related

Query without partition by or functions like rank()

Suppose we have the table students (name, grade, group, year)
We want a query that ranks for each group the corresponding students.
I know that this can be done easy with rank() OVER ( partition by group order by grade DESC ). But I think that this can also be done with a self join or a subquery. Any ideas?
The equivalent to rank() is:
select s.*,
(select 1 + count(*)
from students s2
where s2.group = s.group and
s2.grade > s.grade
) as rank
from students s;

Get top records for each group in sql

I have a table which has 3 columns StudentID, Score and ClassNumber.
What I need now is to select top 5 students of each Class (according to their Score result).
For example if there are 20 students in Class1, 40 students in Class2 and students in Class3, I need to select 15 top score students for each Class(5 for Class1, 5 for Class2, 5 for Class3)
How can I do this in one SQL query?
Do you mean somthing like this?
with tmp as
(
select ClassNumber,
StudentID,
Score,
row_number() over (partition by ClassNumber order by Score desc) row_num,
from Student s
)
select ClassNumber, StudentID, Score
from tmp
where row_num <= 5
order by ClassNumber
Solution in MYSQL :
SELECT StudentID, Score, ClassNumber
FROM
(SELECT StudentID, Score, ClassNumber,
#class_rank := IF(#current_class = classNumber, #class_rank + 1, 1) AS class_rank,
#current_class := ClassNumber
FROM student
ORDER BY ClassNumber, score DESC
) ranked
WHERE class_rank <= 5;
Solution in SQL SERVER:
select ClassNumber, StudentID, Score
from (
select ClassNumber,
StudentID,
Score,
dense_rank() over (partition by ClassNumber order by Score desc) ranking
from Student s
) as t
where ranking <= 5
order by ClassNumber

Selecting Third Highest Value SQLServer [duplicate]

This question already has answers here:
How to find third or nᵗʰ maximum salary from salary table?
(56 answers)
Closed 5 years ago.
I'm trying to return the name & grade of the student with the third highest assessment grade. I'm currently getting the right answer, but I feel like there's a better way to do it.
Dataset
CREATE TABLE Student(
Student_ID INT,
Student_Name VARCHAR(10)
)
INSERT INTO Student (Student_ID, Student_Name) VALUES (1,'Alex'),(2, 'Brett1'),(3,'Cora'),(4,'David'),(5,'Eleanor'),(6,'Brett2')
CREATE TABLE Grades(
Student_ID INT,
Assignment_ID INT,
Grade INT
)
INSERT INTO Grades (Student_ID, Assignment_ID, Grade) VALUES (1,10,90),(2,10,85),(3,10,75),(4,10,74),(1,11,80),(2,11,81),(4,11,88),(6,11,86),(2,12,84)
Attempted Solution
SELECT top 1 s.Student_Name, g.Grade
FROM Student s
INNER JOIN Grades g on s.Student_ID=g.Student_ID
WHERE g.Grade < 88
ORDER BY Grade DESC
Without the (WHERE g.Grade<88) it returns the top 3 results, this was a manual way to fix the issue
Thanks in advance~!
for obtain only the 3rd you could use the TOP 1 reverted of the top 3
select top 1 Student_name, Grade
from (
SELECT top 3 s.Student_Name, g.Grade
FROM Student s
INNER JOIN Grades g on s.Student_ID=g.Student_ID
ORDER BY Grade DESC ) t
order by Grade asc
"Newer" SQL Server versions (SQL Server 2012+):
SELECT s.Student_Name, g.Grade
FROM Student s
INNER JOIN Grades g on s.Student_ID=g.Student_ID
ORDER BY Grade DESC
OFFSET 2 FETCH FIRST 1 ROW ONLY
Use ROW_NUMBER window function
;with cte
AS (
SELECT s.Student_Name, g.Grade ,
RN = row_number()over(order by Grade desc)
FROM Student s
INNER JOIN Grades g on s.Student_ID=g.Student_ID
)
Select *
From cte
Where RN = 3

Find multiple maximum values form a table

I have read answers to similar questions but I cannot find a solution to my particular problem.
I will use a simple example to demonstrate my question.
I have a table called 'Prizes' with two columns: Employees and Awards
The employee column lists the employee's ID and award shows a single award won by the employee. If an employee has won multiple awards their ID will be listed in multiple rows of the table along with each unique award.
The table would look as follows:
Employee AWARD
1 Best dressed
1 Most attractive
2 Biggest time waster
1 Most talkative
3 Hardest worker
4 Most shady
3 Most positive
3 Heaviest drinker
2 Most facebook friends
Using this table, how would I select the ID's of the employees who won the most awards?
The output should be:
Employee
1
3
For the example as both these employees won 3 awards
Currently, the query below outputs the employee ID along with the number of awards they have won in descending order:
SELECT employee,COUNT(*) AS num_awards
FROM prizes
GROUP BY employee
ORDER BY num_awards DESC;
Would output:
employee num_awards
1 3
3 3
2 2
4 1
How could I change my query to select the employee(s) with the most awards?
A simple way to express this is using rank() or dense_rank():
SELECT p.*
FROM (SELECT employee, COUNT(*) AS num_awards,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM prizes
GROUP BY employee
) p
WHERE seqnum = 1;
Being able to combine aggregation functions and analytic functions can make these queries much more concise.
You can use dense_rank to get all the rows with highest counts.
with cnts as (
SELECT employee, count(*) cnt
FROM prizes
GROUP BY employee)
, ranks as (select employee, cnt, dense_rank() over(order by cnt desc) rnk
from cnts)
select employee, cnt
from ranks where rnk = 1

Top 2 Salary Grouped By Department

Below is the table I am referring to.
I want to find ou the 2 Employees in each department with highest salary.
Further to the above answer, if there are ties (multiple employees sharing the same salary), you can use the following to bring them all through instead of just picking two at random (which is what the ROW_NUMBER clause will do)
SELECT *
FROM (
SELECT *, DENSE_RANK() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2
Use ROW_NUMBER() to get the top salaries per Department, then select the first two records from each departmental partiton:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Dept ORDER BY Salary DESC) AS rn
FROM MyTable ) t
WHERE t.rn <= 2