Count the number of employees for supervisor - mysql

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

Related

Subquery joining same table

So i have an employees table:
I'm trying to create a query that displays all the info of this employee but i'm a little stumped at the Employee_Reports_To bit. What i want to appear is the First_Name and Last_Name of the Employee_ID that's stored in this column (Eg Joe Bloggs ID 1, reports to employee Joanne Blog ID 50)
Would this need a join or just a simple select. The database is having issues with the link when i try..
SELECT employee.*, departments.Department_Name,
jobTitle.Job_Title,
(SELECT manager.First_Name, manager.Last_Name
FROM Employee manager
INNER JOIN employee AS employeeReportsTo
ON manager.Employee_Reports_To = manager.Employee_ID
) AS Reports_To
FROM Employee employee
LEFT JOIN Departments AS departments
ON departments.Departments_ID = employee.Departments_ID
LEFT JOIN Job_Title AS jobTitle
ON jobTitle.Job_Title_ID = employee.Job_Title_ID
ORDER BY `employee`.`Record_Active` DESC,
`employee`.`First_Name` ASC
Any assistance would be appreciated!
Try this solution:
SELECT emp.*,
manager.First_Name,
manager.Last_Name,
departments.Department_Name,
jobTitle.Job_Title
FROM Employee emp
INNER JOIN Employee manager
ON emp.Employee_Reports_To = manager.Employee_ID
LEFT JOIN Departments AS departments
ON departments.Departments_ID = emp.Departments_ID
LEFT JOIN Job_Title AS jobTitle
ON jobTitle.Job_Title_ID = emp.Job_Title_ID
ORDER BY emp.Record_Active DESC,
emp.First_Name ASC
It's always better to use Join instead of using Sub Query.
EDITED:
Since column Employee_Reports_To can be null so it's better to use LEFT JOIN instead of INNER JOIN. Like This:
SELECT emp.*,
manager.First_Name,
manager.Last_Name,
departments.Department_Name,
jobTitle.Job_Title
FROM Employee emp
LEFT JOIN Employee manager --Changed Join here
ON emp.Employee_Reports_To = manager.Employee_ID
LEFT JOIN Departments AS departments
ON departments.Departments_ID = emp.Departments_ID
LEFT JOIN Job_Title AS jobTitle
ON jobTitle.Job_Title_ID = emp.Job_Title_ID
ORDER BY emp.Record_Active DESC,
emp.First_Name ASC
Looking to your code you could use two time Employee (with alias e1 and e2) one for employee and one for the related manager
SELECT e1.*
, departments.Department_Name
, jobTitle.Job_Title
, e2.First_Name
,e2.Last_Name
FROM Employee e1
INNER JOIN Employee e2 ON e1.Employee_Reports_To = e2.Employee_ID
LEFT JOIN Departments AS departments
ON departments.Departments_ID = e1.Departments_ID
LEFT JOIN Job_Title AS jobTitle
ON jobTitle.Job_Title_ID = e1.Job_Title_ID
ORDER BY e1.`Record_Active` DESC,
e1.`First_Name` ASC

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

sql, employee and department

Requirements: using one query only to show each department with their employee counts (two tables, department and employee); order by number of employees decreasing;(for departments with no employees, still show them); for departments with the same size, order by department name alphabetically. My solution not showing the departments with no employees, also, it is not showing alphabetically order of departments when same number of employees:
SELECT d.DEPT_ID,
DEPT_NAME, COUNT(s.STUDENT_ID) as numStudents
FROM Departments d, Students s
WHERE d.DEPT_ID = s.DEPT_ID
GROUP BY d.DEPT_ID
ORDER BY numStudents DESC;
Use a LEFT JOIN instead of the cross join you are currently doing.
SELECT d.DEPT_ID,
d.DEPT_NAME, COALESCE(COUNT(s.STUDENT_ID),0) as numStudents
FROM Departments d,
LEFT JOIN Students s
ON s.dept_id = d.dept_id
GROUP BY d.DEPT_ID, d.dept_name
ORDER BY numStudents DESC, DEPT_NAME;
In order to show departments with no students, you have to use LEFT JOIN, not a cross product. And to order by name when they have the same number of students, you need to add that to your ORDER BY clause.
SELECT d.DEPT_ID, DEPT_NAME, IFNULL(COUNT(s.STUDENT_ID), 0) AS numStudents
FROM Departments AS d
LEFT JOIN Students AS s ON d.DEPT_ID = s.DEPT_ID
GROUP BY d.DEPT_ID
ORDER BY numStudents DESC, DEPT_NAME

How to use Union using Inner Join

I have a one to many relationship between departments and users.
Database Design:
users has each own department and department has many users. I wanted to select all the department_name but I have a duplicate values of department_name I want to merge it into one so I planned to use UNION how can I implement this using Inner Join? This is my code so far.
SQL
SELECT D.department_name FROM users U
INNER JOIN departments D ON D.id = U.department_id;
Results:
If you want only the distinct department names, you need to group the users into a comma separated values.
select d.department_name, group_concat(u.id) user_id_list
from departments d inner join users u on d.department_id = u.department_id
group by d.department_name

MySQL count maximum number of rows

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