SQL (two Tables) Query most popular course - sql

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.

Related

SQL on Oracle: Already joined two tables, now i want another column from another table(another join)

I have three tables;
1. Students - id, name
2. Subjects - sid,sname
3. Results - id,sid,marks (id and sid are foreign keys referenced by the two tables above)
Now, i perform
SELECT s.sname AS SubjectName, MAX(r.marks) AS MaxMarks
FROM subjects s, results r
WHERE s.sid=r.sid
GROUP BY r.sid, s.sname
ORDER BY r.sid
and i get The Subject Name with the maximum marks scored in them.
Now further, i also want the student name that has scored these max marks.
So i tried adding the column r.id, didn't work. I tried adding the table students in this query. I'm probably goofing up with the grouping after adding the table or something?
I did this
SELECT r.id AS StudentID, s.sname AS SubjectName, MAX(r.marks) AS MaxMarks
FROM subjects s, results r
WHERE s.sid=r.sid
GROUP BY r.sid, s.sname, r.id
ORDER BY r.sid
and i got each StudentID, with repeated subjects and the marks scored.
Whereas what i basically want is the student who has scored the highest in each subject.
you may use ROW_NUMBER() to tag the student who marked the highest on each subject
SELECT st.name,
sj.sname,
r.marks
FROM (SELECT id,
sid,
marks,
ROW_NUMBER() OVER (PARTITION BY sid
ORDER BY marks DESC) maxmarks
FROM results) r
JOIN students st
ON r.id = st.id
JOIN subjects sj
ON r.sid = sj.sid
WHERE r.maxmarks = 1
you can simple add the new join, and i suggest you the use of explicit join sintax
SELECT t.name, s.sname AS SubjectName, MAX(r.marks) AS MaxMarks
FROM subjects s
INNER JOIN results r ON s.sid=r.sid
INNER JOIN Students t ON t.id = r.id
GROUP BY r.sid, s.sname, t.name
ORDER BY r.sid
In the implicit join sintax should be
SELECT s.sname AS SubjectName, MAX(r.marks) AS MaxMarks
FROM subjects s, results r, stundet t
WHERE s.sid=r.sid
and t.id = r.id
GROUP BY r.sid, s.sname, t.name
ORDER BY r.sid

SQL to Relation Algebra

How can I white this in relation algebra? I'm always getting confused with those GROUP BY and HAVING COUNT...Can't really formulate that.
SELECT DISTINCT Name
FROM studies, course
WHERE (SELECT COUNT(course_id) FROM studies
GROUP BY course_id HAVING COUNT (course_id) > 1) >= 2
AND (SELECT course_id FROM studies
GROUP BY course_id HAVING COUNT (course_id) > 1) = course.course_id;
If I'm understanding your comment correctly, then you just need to join the tables together and use a single group by with having:
select c.course_id, c.name
from course c
join studies s on c.course_id = s.course_id
group by c.course_id, c.name
having count(s.course_id) > 1

Favourite Course in Student Course Table Query

I have three tables:
Student(StudentID, StudentName)
Course(CourseID, CourseName)
StudentCourse(StudentID, CourseID) -- junction table to assign courses to students
How would I query to get the favourite course--"the course which has highest number of students enrolled"?
SQLFiddle
Try it by using TOP...WITH TIES
SELECT TOP 1 WITH TIES c.CourseName,
COUNT(c.CourseID) totalCount
FROM student a
INNER JOIN studentcourse b
ON a.studentID = b.studentID
INNER JOIN course c
ON b.courseID = c.courseID
GROUP BY c.CourseName
ORDER BY totalCount DESC
WITH TIES show the records that have the same highest number of counts.
SQLFiddle Demo
SELECT TOP 1 WITH TIES COURSEID
FROM STUDENTCOURSE
GROUP BY COURSEID
ORDER BY Count(*) DESC

Count within a count

REVISED:
Okay, thanks to all of your input, I figured out what I was doing wrong (sorry guys). I am grabbing the courseID which counts as a section NOT an actual course. For me to grab the actual courseName, I have to go over to the Course Table.
So now I have StudentID from Enrollment and CourseNum from Course that need to be used to count. I'll try and work with what you guys have provided to see if I can come up with the results.
EDIT:
Here's my revised SQL. This provides me with the total courses for each student. I'm getting there:
SELECT Count(DISTINCT Course.courseNum), Grades.studentID
FROM Grades INNER JOIN
Course ON Grades.courseID = Course.courseID
GROUP BY Grades.studentID;
Final Code just in case those who care:
SELECT COUNT(NumCourses) FROM
(SELECT Count(DISTINCT Course.courseNum)AS NumCourses
FROM Grades INNER JOIN
Course ON Grades.courseID = Course.courseID
GROUP BY Grades.studentID
HAVING Count(DISTINCT Course.courseNum) = 1) a;
Try this:
select count(studentId), count(courseId) from enrolment group by courseId having (count(courseId) = 2);
To get the total number of students on 4+ courses, this is the SQL:
SELECT COUNT(CourseCount) AS CourseCount
FROM (
SELECT StudentID, COUNT(CourseID) AS CourseCount
FROM enrollment
GROUP BY StudentID
HAVING (COUNT(CourseID) >= 4)) AS T
It is much simpler to get the student count using a second query.
SELECT COUNT(NumCourses) AS NumStudents, NumCourses FROM (SELECT COUNT(courseID) AS NumCourses FROM enrollment GROUP BY courseID HAVING COUNT(courseID) = 4) As SomeTableAlias
select count(*)
from (select student_id from enrollment group by student_id having count(*) = 4)
The inner query gives you the IDs of the students who enrolled in exactly 4 courses then I count them.
I thought you wanted the number of students who are enrolled in exactly four courses.
If you want to count the number of students and the number of courses, do this:
SELECT * FROM (SELECT COUNT(*) AS NumStudents FROM (SELECT DISTINCT studendid FROM enrollment)), (SELECT COUNT(*) AS NumCourses FROM (SELECT DISTINCT courseid FROM enrollment))
SELECT COUNT(*) FROM
(SELECT COUNT(*) FROM enrollment
GROUP BY studentid HAVING COUNT(*) = 4)

select max for more than one column?

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).