MySQL count maximum number of rows - mysql

I am trying to select the classes with maximum enrollment in each department from a table with the following structure:
Courses: cid, dept, name
Enrollment: cid, sid
The idea would be to count all the enrollments in each class, and find the maximum in each department. Unfortunately, I'm having trouble with the maximum-count combination.
My query was going to look something like:
SELECT c.name, MAX(COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept
But I can't figure out how to get the MAX-COUNT syntax to work properly. I've tried a lot of different examples from Google and StackOverflow and none of them worked for me. MySQL says the syntax is wrong.

I like nested queries for this kind of problem. First select the enrollment counts grouped per class. Then find the max enrollment count grouped per department:
SELECT MAX(cnt) cnt, dept FROM
(
SELECT COUNT(*) cnt, dept, C.cid
FROM Courses C
INNER JOIN Enrollment E on C.cid = E.cid
GROUP BY cid, dept
) a
GROUP BY dept

There is no declaration of E, so you can't use E.cid
So, either you do this
SELECT c.name, COUNT(c.*) as count
FROM Courses C
GROUP BY C.dept
Or,
SELECT c.name, MAX(SELECT COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept

SELECT MAX(cnt) FROM (
SELECT c.name, COUNT(E.*) AS cnt FROM Enrollment E
INNER JOIN Courses C ON E.cid = C.cid
GROUP BY C.dept
) final

Related

Issue with select statements in MySQL past exam paper

Im going over a past paper and have found some select statements I cannot do. Can anyone help with these? I'm using MySQL. Thanks
Schema:
employee = (employee id, name, address, date of birth, salary)
project = (project id, name, budget, start date, end date)
manages = (employee id, project id)
works on = (employee id, project id)
Questions :
Names and addresses of all employees who work on projects which are
current (have not ended yet)
The names of managers of projects, ordered by the total number of employees they manage
The names of employees who work on the project with the largest budget
amount.
My attempts:
1.
select employee.name, address
from employee natural join works_on natural join project
where end_date is null
2.
select employee.name, count(works_on.employee_id) as manages_count
from (employee natural join manages) joins works_on using (employee_id)
I'm completely lost I cannot even attempt this one ^
3.
select employee.name, address, budget
from employee natural join works_on natural join project
order by budget
limit n
^ I know this is wrong as technically I should be able to show them without a limit
Here you go:
1.
select
e.name,
e.address
from employee e
join works_on w on w.employee_id = r.employee_id
join project p on p.project_id = e.project_id
where p.end_date is null
2.
select
n.name
from employee n
join manages m on m.employee_id = n.employee_id
join works_on w on e.project_id = m.project_id
group by n.employee_id
order by count(*) desc
3.
select
e.name
from employee e
join works_on w on w.employee_id = e.employee_id
join project p on p.project_id = w.employee_id
where p.project_id in (
select project_id from project where budget = (
select max(budget) from project
)
)

Finding duplicate values in mysql when joining two tables

I have the following 3 tables for students and I need to find the names of students who currently are enrolled in classes that meet at the same time
student(**snum**, sname, major, level, age)
class(**cname**, meets_at, room)
enroll(**snum**, **cname**)
The keys for each table is in bold.
I have tried the folling code and I'm not sure whether I'm close to the correct answer here.
select s.sname
from student s
join
( select c.cname
, c.meets_at
, (count(*)
from class c
having count( * ) > 1
) e
on c.cname = e.cname
and s.snum = e.snum;
I would think of this as joining on students with meetsat. So, this gets students with their class times:
select s.sname, c.meets_at
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname;
Then, to get the duplicates, use aggregation and filter using having:
select s.snum, s.sname, c.meets_at, count(*) as cnt
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
Note that this includes the ids as well as the name, because two students could have the same name.
Finally, a student could have multiple pairs of classes that conflict, but you only want to see the student once. Although the above is probably sufficient for your purposes, a more accurate solution for the stated problem would be:
select distinct s.sname
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
select s.snum, s.sname, c.meets_at ,count(*) as cnt into #tempStudents
from students s
join enrolls e on s.snum = e.snum
join classes c on c.cname = e.cname;
Put the whole data in temporary table
select sname from #tempStudents
group by snum,sname ,meets_at
having cnt >=2
Now apply filtration on temporary table for getting desire data
and if u need distinct name of student put Distinct keyword before sname.

Sql numbers of employees by department

I have 2 tables employees(id, first_name, last_name, salary, department_id_ and department(id, name) and I want to show number of employees in each department.
I have this question here:
SELECT department.name, COUNT(*) AS 'employees_number'
FROM department
LEFT JOIN employees
ON employees.department_id = department.id
GROUP BY department.id, department.name;
But for some reason, in departments where I have no people, it shows a number of employees as 1. Any idea why this is happening?
With an outer join you still get a result row when no match in the outer table is found. Only all employee column values are null then.
So rather than count the records, you want to count matched records, i.e. where an employee was found and its data is not null. So Count a column in the employee table (nulls are not counted, when counting a column or expression). E.g. use COUNT(e.department_id) or COUNT(e.id):
SELECT d.name, COUNT(e.id) AS employees_number
FROM department d
LEFT JOIN employees e ON e.department_id = d.id
GROUP BY d.id, d.name;
What I prefer though, is to aggregate/count before joining. The query looks a bit more complicated, but is less prone to errors on future query changes:
SELECT d.name, COALESCE(e.how_many, 0) AS employees_number
FROM department d
LEFT JOIN
(
SELECT department_id, COUNT(*) AS how_many
FROM employees
GROUP BY department_id
) e ON e.department_id = d.id;
As it's one aggregated column only you want, you can move the subquery to your SELECT clause and get thus a simpler query:
SELECT
d.name,
(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id = d.id
) AS employees_number
FROM department d;
Using SUM instead of COUNT also can give you what you want:
SELECT
department.name,
SUM(CASE WHEN employees.id IS NOT NULL THEN 1 ELSE 0 END) AS 'employees_number'
FROM department
LEFT JOIN employees
ON employees.department_id = department.id
GROUP BY department.id, department.name;
SQL Fiddle:
http://sqlfiddle.com/#!9/8b8976/1
select department.name, count(employee.id) as co from
department left join employee on
department.id = employee.dept_id group by department.name
order by co desc, department.name asc

how to display the name of the departments that has the least student count

how to write a query to display the name of the departments that have the least student count. Sort the result based on department name in ascending order
select d.department_name from
(select dd.department_name, count(di.department_id) as id from student di
join department dd on di.department_id=dd.department_id group by dd.department_name) d,
(select min(count(*)) as new from student group by department_id) d2
where d.id=d2.new;
select d.department_name from Department d, Student s where
d.department_id = s.department_id
group by d.department_name
having count(s.student_id)<=all
(select count(s.student_id) from Department d, Student s where
d.department_id = s.department_id
group by d.department_name)
order by department_name;
Try this.
select d.department_id, d.department_name
from Department d
join Student s on d.department_id = s.department_id
group by d.department_id
having count(s.student_id) = (select min(count(s2.student_id))
from student s2
join department d2
on s2.department_id = d2.department_id
group by d2.department_id)
order by d.department_name
You must join the 2 tables to have the needed information.
You'll also have to group them by the selected information such that you can count the students.
And lastly, you place the condition. Needing a subquery to retrieve the minimum number of students.
select department_name
from Department
join Student
on Department.department_id=Student.department_id
having count(*) in
( select min(count(*)) from Student group by department_id)
group by Department.department_id,department_name
order by department_name asc;

Count the number of employees for supervisor

SELECT
e.lname AS employee_name
, s.lname AS supervisor_name
, e.superssn AS supervisor_ssn
FROM employee e INNER JOIN employee s
WHERE e.superssn=s.ssn
I actually have two questions. The first one is, the above statement works just fine. However right now it will show bunch of employees with their supervisor. Not well organized. By the way there are three supervisors. Is there a way to show let's say supervisor A with employees A and supervisor B with employees B and so on?
The second problem is that I also tried to just count the number of employees for each supervisor rather than showing their name with COUNT(), I tried several different ones but non worked.
A few things
1) It is good practice to keep your join predicate with your join. So change:
FROM employee e INNER JOIN employee s WHERE e.superssn = s.ssn
To:
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
2) To keep them together by supervisor, just use an order by:
SELECT
e.lname AS employee_name
, s.lname AS supervisor_name
, e.superssn AS supervisor_ssn
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
ORDER BY s.lname
3) To do a count of employees for each supervisor use a group by and the COUNT aggregate function
SELECT
s.lname AS supervisor_name,
COUNT(*) AS employee_count
FROM employee e INNER JOIN employee s ON e.superssn = s.ssn
GROUP BY s.lname
ORDER BY s.lname