How to check the count and based on that query - mysql

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)

Related

OQL and SQL queries. Select all department numbers whose employees have the same salary

So, I have two tables:
EMP {EMP_NO, EMP_SALARY, EMP_DEPT_NO}
DEPT {DEPT_NO, DEPT_MNG}
EMP_NO, DEPT_NO - primary keys, EMP_DEPT_NO - external key to DEPT, DEPT_MNG - external key to EMP.
I need to find all departments where every employee has the same salary.
You can use the COUNT DISTINCT in the HAVING section to achieve that. the COUNT DISTINCT will return how many variations of salary there are in a certain dept.
SELECT DEPT_NO
FROM DEPT JOIN EMP ON DEPT.DEPT_NO=EMP.EMP_DEPT_NO
GROUP BY DEPT_NO
HAVING COUNT(DISTINCT SALARY) =1

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!

SQL count with another table in SELECT clause

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

MYSQL selecting across multiple tables + using mathematical operators Average/Count

I have two tables with the following attributes:
Table: Department
dept_nbr
dept_name
dept_phone
dept_building
dept_mgr
Table: Employee
emp_nbr
emp_lname
emp_fname
emp_phone
emp_dateofbirth
emp_date_hired
emp_nbr_of_dependents
emp_dept
dept_nbr = emp_dept
I need:
for each dept
1.) total no. of employee dependents
2.) average no. of dependents. - i am guessing AVG
3.) total no. of employees - i am guessing count(*)
Could someone please help me counter this?following is my code
select DEPT_NAME, AVG(EMP_NBR_OF_DEPENDENTs), count(emp_fname) as Total_No_of_Employees from dept,employee where DEPT_NBR = EMP_DEPT group by DEPT_NAME;
second part:
include those departments that have fewer than 50 employees
select DEPT_NAME, AVG(EMP_NBR_OF_DEPENDENTs), count(emp_fname) as Total_No_of_Employees from dept,employee where DEPT_NBR in (select EMP_DEPT from employee where count(emp_fname)<50) group by DEPT_NAME ;
i tried the above and got an error 1111
Thanks Heaps
SELECT dept_name,SUM(emp_nbr_of_dependents),AVG(emp_nbr_of_dependents),COUNT(emp_nbr)
FROM deptartment JOIN employee ON dept_nbr=emp_dept
GROUP BY dept_name
HAVING COUNT(emp_nbr)<50
More aggregation functions can be combined in one select.
select DEPT_NAME,
sum(EMP_NBR_OF_DEPENDENTs) employee_dependents_sum,
AVG(EMP_NBR_OF_DEPENDENTs) avg_nbr_dependents,
count(emp_nbr) employee_count
from dept,employee
where DEPT_NBR = EMP_DEPT
group by DEPT_NAME
having employee_count < 50;
WHERE part is applied before GROUP BY and then HAVING is applied on result.
http://dev.mysql.com/doc/refman/5.5/en/select.html

Is my Relation Algebra correct?

I am trying to understand Relation Algebra for my Database Class and I was wondering if someone here can look at what I've done and help me figure out what is correct and what isnt.
What I am trying to solve is: For each department, retrieve the name and the min and max salary range for every employee in that department.
Table Setup:
Employee(Fname, Minit, Lname, Ssn, Bdate, Address, Sex, Salary, Super_ssn, Dno)
Department(Dname, Dnumber, Mgr_ssn, Mgr_start_date)
SQL:
Select Dname, Min(Salary), Max(Salary)
from EMPLOYEE, DEPARTMENT
Where Dnumber = Dno
Group by Dname
Relational Algebra (Step, with one operand per line):
Salaries ← π(Dno, Salary)[EMPLOYEE]
Departments ← π(Dname, Dnumber)[DEPARTMENT]
SalariesD ← Salaries JOIN(Symbol wont work)(Dno=Dnumber) Departments
Selection ← π(Dname, Min(Salary), Max(Salary))[SalariesD]
Results ← Group-Symbol(Dname)[Selection]
Sorry about the formatting. Please let me know if im on the right track with this.
I think this could be also right......
select a.Fname,Max(a.Salary),Min(a.Salary)
from Employee a
join Department b on a.Dno = b.Dnumber
group by Dname