SQL count with another table in SELECT clause - mysql

In my database, have 2 different fields
i.) Employee
ii.) Department
In my employee table,
NAME Department
---------------------
John IT
Siti Research
Jason Research
In my Department,
Name
------------
IT
Research
Computer
Using statement
SELECT DEPARTMENT.DNAME
FROM DEPARTMENT,
EMPLOYEE
WHERE DEPARTMENT.DNAME = EMPLOYEE.DNAME
AND
(SELECT COUNT(*)
FROM EMPLOYEE.DNAME)=0;
when no employee in the department then will display
Name
--------------
Computer
Keep trying but having some error on it

Two alternatives:
Using IN:
SELECT name FROM Department
WHERE name NOT IN (SELECT DISTINCT Department
FROM Employee)
Using Left Join:
SELECT D.NAME
FROM DEPARTMENT D LEFT JOIN EMPLOYEE ON D.NAME = EMPLOYEE.Department
WHERE EMPLOYEE.Department IS NULL
An example in Fiddle.
This method will show higher performance than the other if you have thousands of records in your table.

Try NOT IN. Sub query need to be DISTINCT to avoid performance issue in future:
SELECT name FROM Department
WHERE name NOT IN ( SELECT DISTINCT Department FROM Employee);
Or NOT EXIST, faster in most cases:
SELECT name FROM Department
WHERE NOT EXIST ( SELECT 1 FROM Employee
WHERE Employee.Department = Department.name);

You don't state your error but you can select all departments that don't appear in the employee table:
SELECT DEPARTMENT.DNAME
FROM DEPARTMENT
WHERE DEPARTMENT.DNAME NOT IN (SELECT DEPARTMENT FROM EMPLOYEE);

SELECT D.Name
FROM Employee E
RIGHT JOIN Department D
ON E.Department=D.Name
WHERE E.Department IS NULL
SQL Fiddle DEMO

Related

Department name and number of students

I found one question in MySQL I am trying. Please tell me if following solution will work or is there any better solution?
select D.DEPT_NAME, COUNT(*)
from Departments D
left outer join STUDENTS S
on S.Dept_ID = D.Dept_ID
group by D.DEPT_NAME
order by 2 desc, 1
Students table has following fields:
Student_ID
Student_Name
Gender
Dept_ID
Departments table has following fields:
Dept_ID
Dept_Name
A university uses 2 data tables, Students and Departments, to store data
about its students and the departments associated with each major.
Write a query to print the respective department name and number of students
majoring in each department for all departments in the Departments table
(even ones with no current students).
Sort your results by descending number of students; if two or more departments have same number of students, then sort those departments alphabetically by department name.
Forgive me altering the formatting of the code.
I would change the ORDER BY, as follows:
SELECT
d.DEPT_NAME,
COUNT(s.STUDENT_ID)
FROM
Departments d
LEFT JOIN Students s ON d.DEPT_ID = s.DEPT_ID
GROUP by
d.DEPT_ID
ORDER by
COUNT(s.STUDENT_ID) DESC,
d.DEPT_NAME ASC
You need a way to count the students in each department, then you need a way to list all departments, even those without students.
Counting the students in each department: (http://sqlfiddle.com/#!15/39a8b/15/0)
SELECT Dept_ID, COUNT(*) Students
FROM STUDENTS
GROUP BY Dept_ID
Then, treating that as a subquery, left join it to your other table. (http://sqlfiddle.com/#!15/39a8b/16/0)
SELECT D.DEPT_NAME, S.Students
FROM Departments D
LEFT JOIN (
SELECT Dept_ID, COUNT(*) Students
FROM STUDENTS
GROUP BY Dept_ID
) S ON D.Dept_ID = S.Dept_ID
The LEFT JOIN preserves rows in the DEPARTMENTS table that don't match the ON clause. This gets you stuff like this.
Biology 7
Mathematics (NULL)
Sociology 11
Physics 3
So you have to deal with that (NULL) problem. Here's how. Change the SELECT to say
SELECT D.DEPT_NAME, IFNULL(S.Students,0)
It's a little tricky to join a table to an aggregate where the aggregate (the COUNT/GROUP BY query) has missing data. But that's how you do it.
You can figure out the ORDER BY stuff on your own.
SELECT d.department_name, COUNT(s.student_name) AS student_count
FROM student s
LEFT JOIN department d
ON s.department_id = d.department_id
GROUP BY department_name
ORDER BY d.department_name;
!!This is finally the correct answer !!
Don't hardcode the problem please stay tuned and work like professional
Excute below.
SELECT
ad.Dept_Name,
count(ass.Student_Id) as Stduent_Enrolled
FROM [Alok.Departments] ad
Left Outer Join [Alok.Students] ass
ON ad.Dept_ID = ass.Dept_ID
Group by ad.Dept_Name
ORDER by
CASE WHEN COUNT(ad.Dept_ID) >=2
THEN ad.DEPT_NAME END desc,
CASE WHEN COUNT(ad.Dept_ID) < 2
THEN ad.DEPT_NAME END asc
1 select department_name, count(student_id) as student_count
2 from student
3 left outer join department ON
4 department.department_id=student.department_id
5 group by department_name
6 order by department_name;
#jaat
Use this query
select count(*) from tblstud_info s,tbldept d where s.dno=d.dno group by d.dname

List all employees and the number of people they supervise in mysql

I have a table of employees. Each employee has an employee id. Some employees have a supervisor field that links back to another employee's id. There are 10 employees, two of which are supervisors, each supervising 4 people. I am trying to get a list of all the employees and the number of other employees they supervise. So far I can only seem to get the supervisors and the number they supervise to show. This is my query:
SELECT s.employee_name, COUNT(*)
FROM employee e
join employee s on e.supervisor_id= s.employee_id
group by s.
order by s.employee_name;
I tried changing JOIN to RIGHT JOIN and it will now show me all 10 employees with the two supervisors shown as having 4 people they supervise but it shows all the others having no one to supervise as having 1 instead of 0. I'm sure it's something simple I am missing.
Sample Data:
employee_name, employee_name, supervisor_id,
'10111', 'Sydnee K. Stevens' NULL
'10870', 'Colton C. Rocha', '10111'
'11425', 'Astra V. Sharp','10111'
'12973', 'Melanie X. Rojas','10111'
'14451', 'Bethany Roman','10111'
'14597', 'Lydia Edwards', NULL
'16153', 'Selma Q. Conley', '14597'
'17730', 'Kristen B. Malone', '14597'
'17762', 'Barrett B. Bauer', '14597'
'18628', 'Shana Z. Flowers','14597'
We join your employee table with a select like we would join it with a real table. The select will consist of all supervisor_ids and the number of occurences in the supervisor_id field (records where supervisor_id is null will be ignored).
SELECT e.employee_id, e.employee_name, s.supervising
FROM employee e
LEFT JOIN (SELECT supervisor_id, count(*) as supervising
FROM employee
WHERE supervisor_id is NOT NULL
GROUP BY supervisor_id) AS s
ON(e.employee_id = s.supervisor_id)
Using LEFT or RIGHT JOIN COUNT(*) will always be at least 1. If using LEFT JOIN (RIGHT JOIN is confusing) you just need to count values from a right table column. COUNT(column) will ignore all rows with NULL in that column.
SELECT s.*, COUNT(e.supervisor_id) as num_supervised
FROM employee s
LEFT JOIN employee e on e.supervisor_id = s.employee_id
group by s.employee_id
order by s.employee_name;

Return information about oldest employee in department, if department has more than 20 employees

Don't judge me, I'm new to SQL querying. I got scheme, like the one shown on picture below. So, there are 2 tables, first one Employees contains EmployeeID, FirstName, LastName, DateOfBirth and DepartmentID. The second one is called Department and contains DepartmentID and DepartmentName .
I want to return FirstName, LastName and DepartmentName for the oldest employee from each department containing more than 20 employees.
My solution is the following query :
SELECT FirstName, LastName, DepartmentName
FROM employees
LEFT JOIN department
ON employees.DepartmentID = department.DepartmentID
WHERE (employees.DateOfBirth =
(SELECT MIN(employees.DateOfBirth ) FROM (
SELECT *FROM employees WHERE employees.DepartmentID IN (
SELECT employees.DepartmentID FROM employees GROUP BY DepartmentID HAVING COUNT(*) > 20)));
I think that logic is fine, because inner SELECT statement will return ID's of every department with more than 20 employees, and the outer should return to oldest employee.
The problem that I have is when I try to execute this query, it is returning SQL error every derived table must have it's own alias.
I've tried putting alias on each derived table, but outcome is still the same.
Please, help me with this one.
Also, if someone has different solution, please share it.
Thank You.
Addition which strawberry asked for, Create queries
CREATE TABLE Employees
(
EmployeeID int,
FirstName varchar(10),
LastName varchar(15),
DateOfBirth date,
DeparmentID int
)
CREATE TABLE Department
(
DepartmentID int,
DepartmentName varchar(15)
)
Your query is tricky to read due to inconsistent formatting. So I'll clean it up as follows:
SELECT FirstName, LastName, DepartmentName
FROM employees
LEFT JOIN department
ON employees.DepartmentID = department.DepartmentID
WHERE (employees.DateOfBirth =
(
SELECT MIN(employees.DateOfBirth)
FROM (
SELECT *
FROM employees
WHERE employees.DepartmentID IN (
--Departments with more than 20 employees
SELECT employees.DepartmentID
FROM employees
GROUP BY DepartmentID
HAVING COUNT(*) > 20)
) -- You need an alias here.
-- Also from this point you were missing closing brackets.
Problems with your query:
Obviously the missing alias and closing brackets meant you couldn't even test your query.
Also SELECT MIN(employees.DateOfBirth) returns only a single value. Not a value per department.
So your overall result includes only the oldest employee across all the 'big' departments. (Unless the oldest employee in each department happened to have the same birth date.)
It could also include results from a smaller department if any employee happened to have the same birth date the oldest from the big departments. And that employee needn't even be the oldest in their department!
You also have some inefficiencies by using more sub-queries than necessary.
CTEs (common table expressions) are great at simplifying complex queries. But I don't know if mysql supports them. So this solution still uses sub-queries.
SELECT e.FirstName, e.LastName, d.DepartmentName
FROM employees e -- I prefer short aliases
INNER JOIN (
-- This sub-query returns the earliest birth date within each
-- big department. This needs to be an aliased query so you
-- can join to other tables for your desired columns.
SELECT DepartmentID, MIN(DateOfBirth) AS MinDOB -- Must alias column
FROM employees
WHERE DepartmentID IN (
-- Big departments
SELECT DepartmentID
FROM employees
GROUP BY DepartmentID
HAVING COUNT(*) > 20
)
GROUP BY DepartmentID
) ddob -- Alias Department Date of Birth
-- As a result of inner joining to ddob your employees
-- will be filtered to only those that match the relevant
-- ones identified in the query.
ON e.DepartmentID = ddob.DepartmentID
AND e.DateOfBirth = ddob.MinDOB
INNER JOIN Department d
ON d.DepartmentID = e.DepartmentID
Something to note in the above solution, if 2 employees are tied for being oldest in a department, both will be returned.
This approach is structurally similar to yours, but you could also approach the problem from another direction.
Start out getting oldest employees in ALL departments.
And only at the end filter the result according to department size.
I'll leave that to you to try. I suspect the query would be a little simpler.
The following SQL script correspond to your Class Diagram:
CREATE TABLE Departments (
DepartmentID int AUTO_INCREMENT PRIMARY KEY,
DepartmentName varchar(15)
);
CREATE TABLE Employees (
EmployeeID int AUTO_INCREMENT PRIMARY KEY,
FirstName varchar(10),
LastName varchar(15),
DateOfBirth date,
DepartmentID int,
FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
Following your classes diagram, there is a department for each employee. So, is the reason of using INNER JOIN. I think the following query do what you want:
SELECT ee.FirstName, ee.LastName, ee.DateOfBirth, t.DepartmentName
FROM
(
SELECT e.DepartmentID, d.DepartmentName, MIN(e.DateOfBirth) AS DateOfBirth
FROM Employees AS e
INNER JOIN Departments AS d ON e.DepartmentID = d.DepartmentID
WHERE e.DepartmentID IN (
SELECT DepartmentID
FROM Employees
GROUP BY DepartmentID HAVING COUNT(DepartmentID) > 20
)
GROUP BY e.DepartmentID
) AS t
INNER JOIN Employees AS ee
WHERE ee.DepartmentID = t.DepartmentID AND ee.DateOfBirth = t.DateOfBirth
Example of output:
FirstName LastName DateOfBirth DepartmentName
fisrt14 last14 02/01/2000 SI
fisrt31 last31 12/01/2003 Finance
You improve its performance!

How to check the count and based on that query

I have a table employees and a table department. Each employee is linked to a department id. The fields of the employee table are
EMPLOYEE
ssn, fname, lname, dept_id
DEPARTMENT
dept_id, dept_name
So my problem is that I need to pick the employee name and last name if there are more than 3 employees in a specific department. I am not sure the best way to do this. Any help will be much appreciated.
The main problem is MySQL dislikes queries with subqueries that access same tables.
SELECT d.dept_name, GROUP_CONCAT( CONCAT(E.FNAME,' ',E.LNAME) ORDER BY E.LNAME
SEPARATOR ',' ),
FROM DEPARTMENT D JOIN EMPLOYEE E USING(dept_id)
GROUP BY dept_id
HAVING COUNT(*) > 3;
This solution would provide a list of employess per row per department.
For instance:
'IT', 'Micky Mouse, Tom Jones'
'HR', 'Emily Bronte'
If you prefer, you can change the separator character used in the employees list with SEPARATOR.
Try
SELECT lname, fname
FROM Employee
WHERE dept_id
IN (
SELECT dept_id
FROM Employee
GROUP BY dept_id
HAVING COUNT(*) > 3)

Select records only if another record contains a value from the first record in different field

I haven't had any luck trying to figure this out or what type of statement would be involved if it's possible.
I'm dealing with a company standard 'employees' db. The db has fields for USER_ID and SUPERVISOR_ID. There are no fields to indicate if an employee is a supervisor or if they have subordinates. The only way to know if an employee has subordinates is if any other record has the employee's USER_ID in it's SUPERVISOR_ID field.
I need first_name / last_name based query that only returns employees that have subordinates.
SELECT * from employees e
WHERE e.first_name LIKE '%<first_name_string>%'
AND e.last_name LIKE '%<last_name_string>%'
*(and where at least one record lists this USER_ID in it's SUPERVISOR_ID field)
Thanks for any help!
SELECT * from employees e
WHERE e.first_name LIKE '%<first_name_string>%'
AND e.last_name LIKE '%<last_name_string>%'
AND (SELECT COUNT(*) FROM employees WHERE employees.SUPERVISOR_ID = e.USER_ID) > 0)
select * from employees e
where e.first_name LIKE '%firstnamestring%'
AND e.last_name LIKE '%lastnamestring%'
AND (e.USER_ID in
(select SUPERVISOR_ID from employees))
Try this.