select max for more than one column? - sql

Suppose i have the following table
Students (StudentID, StudentName)
StudentMarks (StudentID, Mark)
I need to select the student with the highest mark.. if there is more than one student have the same mark (and its the highest mark).. then select according to name order (alphabatically)
How can i do this? Thanks in advance

I haven't tested this, but it sounds right
SELECT StudentID, StudentName
FROM Students
JOIN StudentMarks USING (StudentID)
WHERE Mark =
(SELECT MAX(Mark) FROM StudentMarks)
ORDER BY StudentName

SELECT s.StudentName, sm.Mark
FROM Students s
INNER JOIN StudentMarks sm ON sm.StudentID = s.StudentID
WHERE sm.Mark = (SELECT MAX(Mark) FROM StudentMarks)
ORDER BY s.StudentName

how about
select *
from students s
inner join studentmarks m on m.studentid = s.studentid
where m.mark = (select Max(mark) from studentmarks)
order by s.StudentName

Other options
SELECT * FROM Students where StudentId in (SELECT StudentID FROM Mark Where Mark = Max(Max));
or
SELECT s.* FROM Students where exists (SELECT StudentID FROM Mark m Where Mark = Max(Max) and m.StudentId = s.StudentId);

This just needs a simple join and to select the first record.. (by pre-ordering them according to specs)
SELECT TOP 1
S.StudentName, SM.Mark
FROM
Students S
INNER JOIN StudentMarks SM ON SM.studentID = S.StudentID
ORDER BY
SM.Mark DESC,
S.StudentName ASC

If your RDBMS supports analytic functions
WITH Ranked AS
(
SELECT RANK() OVER(ORDER BY Mark DESC) AS Rnk,
Students.StudentID,
Students.StudentName,
Mark
FROM Students
JOIN StudentMarks ON Students.StudentID = StudentMarks.StudentID
)
SELECT StudentID,
StudentName,
Mark
FROM Ranked
WHERE Rnk=1
ORDER BY StudentName
Or for the other interpretation of the spec...
WITH RowNumbered AS
(
SELECT ROW_NUMBER() OVER(ORDER BY Mark DESC, StudentName ASC) AS Num,
Students.StudentID,
Students.StudentName,
Mark
FROM Students
JOIN StudentMarks ON Students.StudentID = StudentMarks.StudentID
)
SELECT StudentID,
StudentName,
Mark
FROM RowNumbered
WHERE Num=1

How about...
SELECT *
FROM Students
WHERE StudentID IN (SELECT StudentID
FROM StudentMarks
WHERE Mark = (SELECT MAX(Mark)
FROM StudentMarks))
ORDER BY StudentName
LIMIT 1;
(expanding on Vash's answer to remove the nonstandard features from it).

Related

Maximum mark in Subject with Staff name

Write a query to display list of staff name, subject name handled, maximum mark scored in that subject. Give an alias to the maximum mark as max_mark. Sort the result based on maximum mark in descending.
This is the schema diagram.
This is the code I have tried.
select distinct
staff_name,
subject_name,
max(value) over (partition by sb.staff_id) as max_mark
from subject sb
inner join staff st
on st.staff_id=sb.staff_id
inner join mark m
on m.subject_id=sb.subject_id
order by max_mark desc;
I was abled to pass one testcase but I could not abled to pass second testcase and I don't know what second testcase is and also I am not getting what I have done wrong in my above code.Is there any way of getting solution for this problem.
It seems that You are looking for the following query:
SELECT
ST.STAFF_NAME,
SB.SUBJECT_NAME,
MAX(M.VALUE) AS MAX_MARK
FROM
STAFF ST
JOIN SUBJECT SB ON SB.STAFF_ID = ST.STAFF_ID
JOIN MARK M ON M.SUBJECT_ID = SB.SUBJECT_ID
GROUP BY
ST.STAFF_ID,
ST.STAFF_NAME,
SB.SUBJECT_ID,
SB.SUBJECT_NAME
ORDER BY
MAX_MARK DESC;
I think that you want aggregation:
select
st.staff_name,
su.subject_name,
max(ma.value) as max_mark
from subject su
inner join staff st on st.staff_id = sb.staff_id
inner join mark ma on ma.subject_id = su.subject_id
group by st.staff_id, st.staff_name, su.subject_id, su.subject_name
order by max_mark desc;
You can use window functions:
select staff_name, subject_name, max_mark
from (select st.staff_name, su.subject_name, ma.value as max_mark,
row_number() over (partition by st.staff_name order by ma.value desc) as seqnum
from subject su join
staff st
on st.staff_id = sb.staff_id join
mark ma
on ma.subject_id = su.subject_id
) s
order by max_mark desc;
You can also use your method (select distinct with window functions) . . . but you have to deal with subject_name:
select distinct staff_name,
first_value(subject_name) over (partition by sb.staff_id order by value desc) as subject_name
max(value) over (partition by sb.staff_id) as max_mark
from subject sb
inner join staff st
on st.staff_id=sb.staff_id
inner join mark m
on m.subject_id=sb.subject_id
order by max_mark desc;

SQL MAX() grouping

Tables:
student(sid, sname, sex, age, year, gpa)
major(dname, sid)
Question:
For each department with more than 15 students majoring in the department, we want to print information about the student(s) with the highest GPA within the department. In particular, for each such student, we want to print the student id, student name and GPA, and the department name the student is major in.
So far I have:
SELECT student.sid, student.sname, student.gpa, major.dname
FROM student
RIGHT JOIN major ON student.sid = major.sid
WHERE student.gpa IN (
SELECT MAX(gpa)
FROM student JOIN major ON student.sid = major.sid
GROUP BY dname
HAVING COUNT(dname) > 15
)
But it doesn't give me the accurate query. The clause inside the IN works but when put together in this way it doesn't actually match student.gpa to dname max GPA. What am I doing wrong here?
This Query gives:
enter image description here
I need:
enter image description here
Your inner query gives you the maximum GPA for each department. Then the outer query returns all students who have a GPA equal to any of the maximum GPA's, regardless of the department. The quickest fix of your code is to use a correlated subquery, that will find the maximum GPA for the student's specific department.
SELECT s.sid, s.sname, s.gpa, sm.dname
FROM student s
RIGHT JOIN major sm ON s.sid = sm.sid
WHERE student.gpa IN (
SELECT MAX(ds.gpa)
FROM student ds JOIN major dm ON ds.sid=dm.sid
WHERE dm.dname = sm.dname
GROUP BY dm.dname
HAVING COUNT(dm.dname)>15
)
This query:
select dname, max(s.gpa) maxgpa
from major m inner join student s
on s.sid = m.sid
group by dname
having count(s.sid) > 15
returns all the departments with more than 15 students and the highest gpa in that department.
Join it to the 2 tables like this:
select s.sid, s.sname, s.gpa, t.dname
from (
select dname, max(s.gpa) maxgpa
from major m inner join student s
on s.sid = m.sid
group by dname
having count(s.sid) > 15
) t
inner join major m on m.dname = t.dname
inner join student s on s.sid = m.sid and s.gpa = t.maxgpa
Or with window functions:
select t.sid, t.sname, t.gpa, t.dname
from (
select m.dname, s.*,
rank() over (partition by m.dname order by s.gpa desc) rn,
count(s.sid) over (partition by m.dname) counter
from major m inner join student s
on s.sid = m.sid
) t
where t.counter > 15 and t.rn = 1
If you change your WHERE ... IN statement to be an INNER JOIN, you can connect more fields.
SELECT student.sid, student.sname, student.gpa, major.dname
FROM student
RIGHT JOIN major
ON student.sid = major.sid
INNER JOIN (
SELECT MAX(gpa) as max_gpa, dname
FROM student JOIN major ON student.sid=major.sid
GROUP BY dname
HAVING COUNT(dname)>15
) as dept_gpa
ON student.gpa = dept_gpa.max_gpa
AND major.dname = dept_gpa.dname

SQL (two Tables) Query most popular course

I am having trouble returning the most common course
Question is: Write a Query to return the CourseName of the most common course
Tables
StudentCourses:
StudentCourseID
StudentID
CourseID
Courses:
CourseID
CourseName
I have this
SELECT CourseName
From Courses c
WHERE CourseID = (SELECT Count(CourseID) AS Course_Value
FROM StudentCourses
Group BY CourseID
Order BY Course_Value DESC
LIMIT 1;
I know it isnt correct but am i correct using COUNT to find the most popular course correctly?
SELECT Top 1 CourseName
FROM Courses
JOIN StudentCourses
ON Courses.CourseId = StudentCourses.CourseId
GROUP BY CourseName
ORDER BY Count(CourseName) DESC
For this type of question, learn to use explicit join and top:
select top (1) c.courseid, c.coursename, count(*) as cnt
from studentcourses sc join
courses c
on sc.courseid = c.courseid
group by c.courseid, c.coursename
order by count(*) desc;
If you want ties, then use top with ties.

Write a query to get name and marks of second highest scorer for every course

Write a query to get name and marks of second highest scorer for every course.
This will give you second highest marks
Select
(SELECT MAX(Marks) FROM Marks
WHERE Marks NOT IN
(SELECT MAX(Marks) FROM Marks)) AS 'Second Highest'
from Marks
WITH MarksCTE AS
(
Select DENSE_RANK() OVER (PARTITION BY CourseID ORDER BY Marks desc) as Rank, m.Marks,c.Name as Course,s.Name as Student
From Marks as M
Inner Join Student as s on S.Id = M.StudentID
Inner Join Course as c on c.Id = M.CourseID
)
Select Marks,Course,Student from MarksCTE where Rank = 2

Getting student name from student table belonging to a section with less than 5 students enrolled

Hello there, I have a questions for you guys. You see enrollment and student table in images below. I want to run a query getting first and last name from student table but students should belong to a section with less than 5 enrolled students.
Does that make any sense? If i am not clear please do ask me a question. Any help with this is greatly appreciated.
Why access one table more than once, if you can save some work by using analytic functions?
select
first_name, last_name
from
(
select
s.first_name, s.last_name, count(*) over(partition by e.section_id) as enrollment_count
from
student s
join enrollment e using (student_id)
)
where
enrollment_count < 5;
This should work.
SELECT s.FIRST_NAME, s.LAST_NAME
FROM student s
WHERE s.STUDENT_ID IN (
SELECT e1.STUDENT_ID
FROM e1.enrollment
WHERE e1.SECTION_ID IN (
SELECT e2.SECTION_ID
FROM e2.enrollment
GROUP BY e2.SECTION_ID HAVING COUNT(DISTINCT e2.STUDENT_ID) < 5
)
)
select t2.first_name, t2.last_name
from table2 t2
inner join
(select student_id from table1 where section_id in
(select section_id from
(select section_id, count(student_id)
from table1
group by section_id
having count(student_id) < 5
)
)
)t1
on t1.student_id = t2.student_id;
Its not pretty, but it should work.