DEPARTMENT Table
DEPARTMENT_ID
| 1 |
| 2 |
EMPLOYEES Table
EMPLOYEE_ID | DEPARTMENT_ID
ANDY | 1
Output
DEPARTMENT_ID|
2
Here is my code:
SELECT DEPARTMENT_ID
FROM DEPARTMENTS
where department_id!= all ( SELECT department_id
FROM employees
);
The code doesn't show 2,and the output is blank.
Like this:
DEPARTMENT_ID|
If you want to find the number of each employee in each department, you should use a left join aggregation:
SELECT d.DEPARTMENT_ID, COUNT(e.EMPLOYEE_ID) AS cnt
FROM DEPARTMENT d
LEFT JOIN EMPLOYEES e
ON d.DEPARTMENT_ID = e.DEPARTMENT_ID
GROUP BY d.DEPARTMENT_ID;
The above count expression counts the EMPLOYEE_ID column in the employee table. It is important to note that should a department have no employees, then COUNT would return zero, since NULL is not counted.
SELECT d.department_id
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
WHERE e.department_id IS NULL
SQLFiddle Demo
Related
I have 3 tables employee, jobs and department as below,
------------------- ---------------- ------------------
| employee | | jobs | | department |
------------------- ---------------- ------------------
| empId | | jobId | | deptId |
| fname | | jobTitle | | deptName |
| lname | | | | managerId |
| jobId | | | | |
| managerId | | | | |
| departmentId | | | | |
------------------- ---------------- -------------------
I want to select all data from employee, the job title through jobId, the deptName through deptId and manager name through managerId and employeeId
SELECT EMPLOYEES.EMPLOYEE_ID, EMPLOYEES.FIRST_NAME, EMPLOYEES.LAST_NAME,
EMPLOYEES.JOB_ID, JOBS.JOB_TITLE AS JOB_TITLE, EMPLOYEES.SALARY,
DEPARTMENTS.DEPARTMENT_ID, DEPARTMENTS.DEPARTMENT_NAME AS DEPARTMENT_NAME
FROM EMPLOYEES
LEFT JOIN JOBS ON EMPLOYEES.JOB_ID = JOBS.JOB_ID
LEFT JOIN DEPARTMENTS ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
what should I do to get the name of the manager using the empId?
or is there any other way to simplify this block of code?
Just Add another LEFT JOIN to the EMPLOYEES table, but give it an alias, say MANAGERS.
SELECT
EMPLOYEES.EMPLOYEE_ID,
EMPLOYEES.FIRST_NAME,
EMPLOYEES.LAST_NAME,
EMPLOYEES.JOB_ID,
JOBS.JOB_TITLE AS JOB_TITLE,
EMPLOYEES.SALARY,
DEPARTMENTS.DEPARTMENT_ID,
DEPARTMENTS.DEPARTMENT_NAME AS DEPARTMENT_NAME,
MANAGERS.FIRST_NAME AS MANAGER_FIRST_NAME,
MANAGERS.LAST_NAME AS MANAGER_LAST_NAME
FROM EMPLOYEES
LEFT JOIN EMPLOYEES MANAGERS
ON EMPLOYEES.MANAGER_ID = MANAGERS.EMPLOYEE_ID
LEFT JOIN JOBS
ON EMPLOYEES.JOB_ID = JOBS.JOB_ID
LEFT JOIN DEPARTMENTS
ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
You can use another left join on employee table to get the manager name.
SELECT (
EMPLOYEES.EMPLOYEE_ID,
EMPLOYEES.FIRST_NAME,
EMPLOYEES.LAST_NAME,
EMPLOYEES.JOB_ID,
JOBS.JOB_TITLE AS JOB_TITLE,
EMPLOYEES.SALARY,
DEPARTMENTS.DEPARTMENT_ID,
DEPARTMENTS.DEPARTMENT_NAME AS DEPARTMENT_NAME,
(MGR.FIRST_NAME + ' ' + MGR.LAST_NAME) AS MANAGER_NAME)
FROM EMPLOYEES
LEFT JOIN JOBS
ON EMPLOYEES.JOB_ID = JOBS.JOB_ID
LEFT JOIN DEPARTMENTS
ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
LEFT JOIN EMPLOYEES MGR
ON EMPLOYEES.MANAGERID = MGR.EMPLOYEE_ID
try using aliases and join back to employee on the manager id.
SELECT
E.EMPLOYEE_ID, E.FIRST_NAME, E.LAST_NAME,
E.JOB_ID, J.JOB_TITLE AS JOB_TITLE, E.SALARY,
D.DEPARTMENT_ID, D.DEPARTMENT_NAME AS DEPARTMENT_NAME,
M.EMPLOYEE_ID as mgr_id, M.FIRST_NAME as mgr_name, M.LAST_NAME as mgr_lname
FROM EMPLOYEES E LEFT JOIN JOBS J ON
E.JOB_ID = J.JOB_ID
LEFT JOIN DEPARTMENTS D ON
E.DEPARTMENT_ID = D.DEPARTMENT_ID
join employees M ON
E.manager_ID = M.employee_ID
The reason this query works is because I am doing a self join back to the Employees table from the main result set that you already established. To put it simply, imagine you made an exact copy of the employees table and called it M. If you took your original query and joined to the M table using the original query's Employee.manager_id to the employee_ID in the M table, then you would have the manager for the employee.
There is no need to create an exact copy of the employee table just to look up the manager. We can just reference the employee table a second time and use an alias (I used M for manager). Then we join from your list of employees using the manager_id to get the employee's manager.
You could do this again to get the manager's manager if you need to. Here is that query:
SELECT
E.EMPLOYEE_ID, E.FIRST_NAME, E.LAST_NAME,
E.JOB_ID, J.JOB_TITLE AS JOB_TITLE, E.SALARY,
D.DEPARTMENT_ID, D.DEPARTMENT_NAME AS DEPARTMENT_NAME,
M.EMPLOYEE_ID as mgr_id, M.FIRST_NAME as mgr_name, M.LAST_NAME as mgr_lname
FROM EMPLOYEES E LEFT JOIN JOBS J ON
E.JOB_ID = J.JOB_ID
LEFT JOIN DEPARTMENTS D ON
E.DEPARTMENT_ID = D.DEPARTMENT_ID
join employees M ON /* The employee's manager */
E.manager_ID = M.employee_ID
LEFT join employees MM ON /* The employee's manager's manager */
M.manager_ID = MM.employee_ID
I used a left join for this last one, because at some point you will get to the top of the management hierarchy and might find that there are no more managers. You could also put a left join on the join employees M
Here it is in Tabular form
Employee_id | Name | manager_id
1 | Fred | 10
2 | Jane | 10
10 | Bob | 20
20 | Betty | Null
Looking at employee # 1. The values of E.employee_id = 1, E.Name = Fred and E.manager_id = 10.
So the relevant lines of the query evaluate as follows:
...
join employees M ON /* The employee's manager */
E.manager_ID /* i.e. 10 */ = M.employee_ID
...
So the M alias now refers to the employee record where M.employee_ID = 10 and as such, M.Name = Bob and M.employee_id = 20.
Using the last version of the query, we could then work out that Fred's manager's manager (i.e. Fred's manager is Bob and Bob's manager is Betty) will have an employee_id of 20 (i.e. M.manager_ID = 20), so the MM.employee_id would be 20 and hence refer to Betty who doesn't seem to have a manager.
I have a query like this:
select employee_id, salary
from salary
left join employee on salary.employee_id=employee.id_employee;
It returns me these results
EMPLOYEE ID | SALARY
-------------|-------
1 | 50
2 | 50
3 | 50
1 | 30
How do I remove duplicates by adding them up, like this:
EMPLOYEE ID | SALARY
------------|--------
1 | 80
2 | 50
3 | 50
There is no reason for a left join from salary to employee. Presumably, every employee_id in salary refers to a valid employee. So, this should do what you want:
select s.employee_id, sum(s.salary) as salary
from salary s
group by s.employee_id;
If you want all employees, even those who are not in the salary table, then an outer join is appropriate -- but employee should be first:
select e.id_employee, sum(s.salary) as salary
from employee e left join
salary s
on s.employee_id = e.id_employee
group by e.id_employee;
Employees not in salary will have a value of NULL.
Note that the group by condition in this query is on employee, the first table in the left join.
select employee_id, SUM(salary) as salary
from salary
left join employee on salary.employee_id=employee.id_employee
group by emplyee_id;
This is exactly what a group by clause is for. You'll have to group by the emplopyee_id and specify how you want to aggregate the salary:
SELECT employee_id, SUM(salary)
FROM salary
GROUP BY employee_id
I used this query:
select D.DeptID, D.Dept, count(E.EmployeeID) as TotalStaff
from Employees as E
right join Departments as D
on D.DeptID = E.DeptID
group by D.DeptID, D.Dept;
To return this:
DeptID_|_Dept___________|TotalStaff
40 | Marketing | 2
50 | Accounting | 3
60 | Manager | 3
70 | GeneralStaff | 1
80 | HumanResources | 1
90 | Production | 0
100 | Sales | 0
Now I want to list the department ID, department and the number of employees for the department that has the lowest number of employees so I tried this:
SELECT MIN(mycount)
FROM
(
select D.DeptID, count(E.EmployeeID) as mycount
from Employees as E
right join Departments as D
on D.DeptID = E.DeptID
group by D.DeptID
);
But I get an error that states: Incorrect syntax near ';'.
All I want to do is return the department that has the lowest amount of employees. Please could anyone help me with this.
please try with below query:
For minimum value:
select min(A.mycount) as min_count
from (
select D.DeptID, count(E.EmployeeID) as mycount
from Departments as D
left outer join Employees as E on D.DeptID = E.DeptID
group by D.DeptID
) as A
For maximum value:
select max(A.mycount) as max_count
from (
select D.DeptID, count(E.EmployeeID) as mycount
from Departments as D
left outer join Employees as E on D.DeptID = E.DeptID
group by D.DeptID
) as A
You have missed the subquery alias
So, your subquery has alias like that
SELECT MIN(mycount)
FROM (select D.DeptID, count(E.EmployeeID) as mycount
from Employees as E
right join Departments as D on D.DeptID = E.DeptID
group by D.DeptID
) s; -- alias missed
The normal way to write this query is to use the ANSI standard rank() function:
select d.*
from (select D.DeptID, D.Dept, count(E.EmployeeID) as TotalStaff,
rank() over (order by count(E.EmployeeID) asc) as seqnum
from Departments d left join
Employees E
on D.DeptID = E.DeptID
group by D.DeptID, D.Dept
) d
where seqnum = 1;
Notice that I also switched the JOIN to a LEFT JOIN. LEFT JOIN is generally simpler to follow (at least for people who read languages left-to-right) because it says to keep all rows in the first table rather than the last table.
try adding
as tablename
after your last ) and before the final ;
I have this task for Oracle. It requires me to display the departments names(department is a table containing the manager_id for that table, department_id and department_name), the manager_id for that department, the name of the manager(found in employees table) and the average salary for that department(salary of each employee is also found in employees). As soon as I try to retrieve the manager name(I suppose by comparing his id in dept with the one in employees) it messes up my averages. Without it(Like following) it works just fine
SELECT d.department_name, AVG(e.salary) as "Salaries"
FROM employees e join departments d on e.department_id=d.department_id
WHERE d.manager_id=e.employee_id
GROUP BY e.department_id, d.department_name,d.manager_id
ORDER BY AVG(e.salary)
Can someone help me solve this and perhaps explain why I mess it up?
WITH factoring clause selects average salary; it is then joined to other tables
SQL> with avgsal as
2 (select e.department_id, round(avg(e.salary)) avg_sal
3 from employees e
4 group by e.department_id
5 )
6 select d.department_id,
7 d.department_name,
8 m.last_name manager,
9 a.avg_sal
10 from departments d
11 join employees m on m.department_id = d.department_id
12 and m.employee_id = d.manager_id
13 join avgsal a on a.department_id = d.department_id
14 order by a.avg_sal;
DEPARTMENT_ID DEPARTMENT_NAME MANAGER AVG_SAL
------------- -------------------- ------------------------- ----------
50 Shipping Fripp 3476
30 Purchasing Raphaely 4150
10 Administration Whalen 4400
60 IT Hunold 5760
40 Human Resources Mavris 6500
100 Finance Greenberg 8601
80 Sales Russell 8956
20 Marketing Hartstein 9500
70 Public Relations Baer 10000
110 Accounting Higgins 10154
90 Executive King 19333
11 rows selected.
SQL>
A quick check for 2 departments:
SQL> select department_id, round(avg(salary)) avg_sal, count(*) "# of employees"
2 from employees
3 where department_id in (20, 30)
4 group by department_id
5 order by 1;
DEPARTMENT_ID AVG_SAL # of employees
------------- ---------- --------------
20 9500 2
30 4150 6
SQL>
Introduce a correlated subquery in select for manager name in your query.
SELECT d.department_name,
AVG(e.salary) AS "Salaries",
(SELECT first_name
||' '
||last_name
FROM employees i
WHERE i.employee_id = d.manager_id) AS manager_name
FROM employees e
join departments d
ON e.department_id = d.department_id
GROUP BY e.department_id,
d.department_name,
d.manager_id
ORDER BY Avg(e.salary);
I have two query results:
Select avg(salary), department_id
from employees
Group by department_id
and
Select d.department_name, e.department_id
From departments d, employees e
Where e.department_id=d.department_id
How can I combine the into one result. Dept. ID on first is primary key for both tables
I tried union, creating new tables... Nothing works I need something like this:
Dept_id | Dept_name | avg_salary |
---------------------------------------
121 | Management | 324000 |
---------------------------------------
102 | Tax | 432555 |
---------------------------------------
Etc
I am assuming you want avarage salary for each department. For that you shoudl use the JOIN with group by. And AVG aggregate to get the average salary for the department.Try this,
SELECT
d.department_id,
d.department_name,
AVG(e.Salary) AS avarageSalary
FROM
Department d JOIN Employee e
ON d.department_id= e.department_id
GROUP BY
d.department_id,d.department_name