MySQL query the largest amount present in a collection - mysql

I have a table Teacher that contains a TeacherPIN as well as a table Student that contains a TeacherPIN referencing a Teacher. The idea is that a Teacher contains a certain amount of Students.
I am tasked with finding the teacher with the most students. I am currently using the query:
select t.TeacherPIN, count(s.TeacherPIN)
from Teacher t, Student s
where t.TeacherPIN = s.TeacherPIN
and ((select count(s1.TeacherPIN) from Student s1 where s1.TeacherPIN = t.TeacherPIN) >=
(select count(s2.TeacherPIN) from Student s2 where s2.TeacherPIN = (select t1.TeacherPIN from Teacher t1)));
I'm sure I'm making this way more complicated than I should be, but I've been at it for a while now and am hoping someone could push me in the right direction.
Thanks!

To find just one teacher (of possibly many) with maximum number of students:
SELECT TeacherPIN
, COUNT(*) AS NumberOfStudents
FROM Student
GROUP BY TeacherPIN
ORDER BY NumberOfStudents DESC
LIMIT 1
To find all of them:
SELECT TeacherPIN
, COUNT(*) AS NumberOfStudents
FROM Student
GROUP BY TeacherPIN
HAVING COUNT(*) =
( SELECT COUNT(*) AS NumberOfStudents
FROM Student
GROUP BY TeacherPIN
ORDER BY NumberOfStudents DESC
LIMIT 1
)

Related

SQL: counting the number of rows and returning all rows with max count: invalid use of group function

I have these tables:
tutors:
tutorid firstname, lastname...
courses:
url tutorid
reviews:
review courseid
I need to select all tutors that have the most reviews. 1 tutor = 1 course.
I first tried to just select courses with the most reviews:
select y.courseid, num from (select courseid,COUNT(reviews.rating) as num
from reviews group by (reviews.courseid)) y;
This selects all urls and the number of reviews for each.
this
select y.courseid, MAX(num) from (select courseid,COUNT(reviews.rating) as num
from reviews group by (reviews.courseid)) y;
would display the single course with most reviews - even if there are other courses with the same (maximum) number of reviews - they won't get displayed.
I'm trying to combat that. I tried
select y.courseid, num from (select courseid,COUNT(reviews.rating) as num
from reviews group by (reviews.courseid)) y
where num = MAX(num);
but get invalid use of group function error.
EDIT: the courseid - is the course's url. As in the course's url is the foreign key in the reviews table.
I would try this one:
select distinct t.tutorid t.firstname, t.lastname
from (select courseid, count(reviews.rating) total
from reviews
group by courseid) r
left join courses c
on r.courseid = c.courseid
left join tutors t
on c.tutorid = t.tutorid
where r.total=(select max(total)
from (select courseid,
count(reviews.rating) total
from reviews
group by courseid) r
)
You can create a column that rank the review in desc order and select those tutor with rank = 1
It would look like this:
Select * from(Select *, rank() over(order by num desc) as rank from table) where rank = 1
You can also use dense_rank base on your need.

ERROR is "group function is nested too deeply"?

tried to display the name of the department that has the least student count.
Try something like this:
SELECT TOP 1 department_name, count(*) AS number_of_students
FROM department natural join student
GROUP BY department_name
ORDER BY number_of_students
It will give you the list of departments ordered by the number of students. By selecting only the first row via TOP 1 you will only get the department with the least number of students.
Is it like this way?
SELECT
T1.department_name, COUNT(T2.department_id) totalCount
FROM department T1
LEFT JOIN student T2
ON T1.department_id = T2.department_id
GROUP BY T2.department_id
HAVING COUNT(T2.department_id) =
(
SELECT
COUNT(T2.department_id) totalCount
FROM department T1
LEFT JOIN student T2
ON T1.department_id = T2.department_id
GROUP BY T2.department_id
ORDER BY totalCount ASC
LIMIT 1
)
SQLFIDDLE DEMO

Finding teacher that only taught one class

I want to ask what would I add to my query to select the ones that only taught one class. My table is:
Teacher Course
ID Name Course_ID Teacher_ID
1 George 1 1
2 Sam 2 2
3 Julie 3 1
I want to get the teacher ID who only taught one class. I have:
select teacher.id
from teacher, course
where teacher.id = course.teacher_id;
I was thinking of adding
having (count(course.teacher_id)) = 1
or
where count(t) = (select count(*) from course) and t = 0
but I get an "invalid use of group error". How do I change it to fix my query?
What you have tried is almost there, just add group by, and use join not , to combine tables:
select teacher.id
from teacher
join course
on teacher.id = course.teacher_id
group by teacher.id
having (count(course.Course_ID)) = 1 -- note count(Course_ID), not count(teacher_id)
Please try below code.Hope this will helps.
select teacher.id
from teacher, course
where teacher.id = course.teacher_id
GROUP BY course.teacher_id
HAVING COUNT(course. Course_ID) =1
Join with a group by and having:
select *
from teacher
where id in (
select teacher_id
from course
group by teacher_id
having count(*) = 1)

How to count MySQL results in a has-many-through relation

There is pretty good article how to filter results in a has-many relation:
How to filter SQL results in a has-many-through relation
I'm just seeking a solution for COUNT result, not show them all.
student {
id
name
}
club {
id
name
}
student_club {
student_id
club_id
}
How many students are in both CLUB1 && CLUB2?
EDIT:
It would be great to use "Martin 2" method from a link below:
SELECT s.stud_id, s.name
FROM student s
JOIN student_club sc USING (stud_id)
WHERE sc.club_id IN (30, 50)
GROUP BY 1,2
HAVING COUNT(*) > 1;
Just adding something to COUNT results.
Probably simplest, cleanest and fastest for just two students:
SELECT count(*) AS ct
FROM student_club x
JOIN student_club y USING (stud_id)
WHERE x.club_id = 30
AND y.club_id = 50;
You don't need to join to the student table for this at all - as soon as you know the list of stud_id you are interested in.
For any number of students, Martin's query is more convenient. You can simplify in a similar fashion:
SELECT count(*) AS ct
FROM (
SELECT stud_id
FROM student_club
WHERE club_id IN (30, 50)
GROUP BY 1
HAVING count(*) = 2 -- adapt to number of items in list
) x;
Requires that (stud_id, club_id) is unique of course, and that list items are also unique.
The query uses table aliases for tables student_club and club. This allows to return rows only for students who are in both clubs. Then, using COUNT allows to return the number of students:
SELECT COUNT(*) AS nb
FROM student s, student_club sc1, club c1, student_club sc2, club c2
WHERE s.id=sc1.student_id AND sc1.club_id=c1.id AND c1.name="CLUB1"
AND s.id=sc2.student_id AND sc2.club_id=c2.id AND c2.name="CLUB2"
If you really want to use the "Martin 2" query, you may count the number of records this way:
SELECT COUNT(*) AS nb
FROM (
SELECT s.stud_id, s.name
FROM student s
JOIN student_club sc USING (stud_id)
WHERE sc.club_id IN (30, 50)
GROUP BY 1,2
HAVING COUNT(*) > 1
) tmp;

count most occurences with the WHERE from other table

I have a movie DB to organize my collection but also I'm using it to learn more of mySQL. along the development I find bumps (plenty of them) and right now my problem is this:
Table ACTORS:
id_actor
name
sex
Table MOVIEACTORES:
id_movieactores
id_movie
id_actor
I want to count the TOP 5 (top10, top20 or whatever!) of actors with most movies and then the Top5 of actresses with most movies!
I have this:
SELECT filmesactores.id_actor,
COUNT( * ) AS contagem
FROM filmesactores
GROUP BY id_actor
ORDER BY contagem DESC
LIMIT 10
But this code doesn't discriminates actors from actresses. I feel the solution might be simple but with my knowledge is out of my reach right now. Anyone?
Grouping by sex, name would separate actors' counts by gender, but since you want to apply the limit to each gender group (i.e. top 5 actors and top 5 actresses), perform two queries and UNION their results together:
SELECT name, COUNT(*) AS moviecount
FROM actors
JOIN movieactores ON actors.id_actor = movieactores.id_actor
WHERE sex = 'Male'
GROUP BY name
ORDER BY COUNT(id_movie) DESC
LIMIT 5
UNION
SELECT name, COUNT(*)
FROM actors
JOIN movieactores ON actors.id_actor = movieactores.id_actor
WHERE sex = 'Female'
GROUP BY name
ORDER BY COUNT(id_movie) DESC
LIMIT 5