I was asked during an interview about this SQL question.
Given Employee table
LastName DepartmentID
Rafferty 31
Jones 33
Heisenberg 33
Robinson 34
Smith 34
Daniel 34
Williams NULL
and Department table
DepartmentID DepartmentName
31 Sales
33 Engineering
34 Clerical
35 Marketing
How could I find ALL of the employees who is at the same department as 'Robinson'? (through a generic way)
Is join (inner join) something that he wanted me to do?
You can use IN:
select *
from employee
where departmentId in (
select departmentId
from employee
where LastName = 'Robinson'
);
Using JOIN:
select e.*
from employee e
join (
select distinct departmentId
from employee
where LastName = 'Robinson'
) e2 on e1.departmentId = e2.departmentId;
Related
I have an employee table that lists all employees and the ID of their manager. The Manager ID refers back to the employee id in this table. I would like to add another column that returns the name of the manager since no one knows their ID numbers.
Current table is basically:
ID Name ManagerID
31 John Smith 10
32 Barb Jones 10
33 Craig Adams 32
I would like to add another column that looks up looks up the manager ID in the ID field and returns the assocaited name like below:
ID Name ManagerID ManagerName
31 John Smith 10 Ted Fish
32 Barb Jones 10 Ted Fish
33 Craig Adams 32 Barb Jones
You can use self-join here.
select e.ID, e.Name, m.ManagerID, e.Name as ManagerName
from employee e
inner join employee m
on e.ID = m.ManagerID;
Here are the details of the tables:
Employee :
emp_ID | Primary Key
emp_name | Varchar
emp_email | varchar <br>
emp_dept_id | Foreign Key
Departments :
dept_ID | Primary Key
dept_name | Varchar
emp_id | Foreign Key
Manager details are already there in the employee table.
I am using Oracle Database.
Employee:
emp_ID emp_name emp_email emp_dept_id
1 Cyrus abc#xyz.com 10
2 Andrew xyz#abc.com 20
3 Mark xyz#abc.com 10
4 Tony xyz#abc.com 10
5 Elvis xyz#abc.com 20
6 Rock xyz#abc.com 10
7 George xyz#abc.com 20
8 Mary xyz#abc.com 10
9 Thomas xyz#abc.com 20
10 Martin xyz#abc.com 10
Depqartments:
dept_id dept_name emp_id
10 Accounts 4
20 Development 9
These are the data in the tables. In Department table, emp_id(Foreign key) indicates the head/manager of the department .
You can try following query:
SELECT
D.DEPT_ID,
D.DEPT_NAME,
D.EMP_ID AS MANAGER_ID,
E.EMP_NAME AS MANAGER_NAME,
E.EMP_EMAIL AS MANAGER_EMAIL,
E.CNT AS "number of employees"
FROM
DEPARTMENT D
JOIN (
SELECT
EMP_ID,
EMP_NAME,
EMP_EMAIL,
EMP_DEPT_ID,
COUNT(1) OVER(
PARTITION BY EMP_DEPT_ID
) AS CNT
FROM
EMPLOYEE
) E ON ( E.DEPT_ID = D.EMP_DEPT_ID
AND E.EMP_ID = D.EMP_ID );
Cheers!!
This is pretty straightforward. You want to get the department details (1) and also include the employees associated with that department (2).
Get the department details:
SELECT <dept_col1>, <dept_col2>, ...
FROM Department
Get a summary of employees per department:
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
Here you replace <aggregation> with whatever you're trying to find. In your case it would be COUNT(*).
Combine the two results. You want to join the data from (2) to (1). How are these two tables related? Here you write a LEFT JOIN to connect them on the PK/FK relationship:
SELECT
dept.<col1>, dept.<col2>, ...,
COALESCE(emp.MyAgg,0) AS MyAgg
FROM Department dept
LEFT JOIN (
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
) emp ON dept.<FK> = emp.<PK>
Get the department manager's info by adding another LEFT JOIN:
SELECT
dept.<col1>, dept.<col2>, ...,
mgr.<col1>,
COALESCE(emp.MyAgg,0) AS MyAgg -- In case there are 0 employees
FROM Department dept
LEFT JOIN employee mgr ON dept.<FK> = mgr.<PK>
LEFT JOIN (
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
) emp ON dept.<FK> = emp.<PK>
Give it a try and see how far you get. If you get stuck let me know.
I have a database:
Staff Name
1 Blake
2 Jake
Mgr Emp
2 6
2 8
3 5
4 7
Is it possible to search up all employees but list them under the manager?
Select all:
Staff Name Mgr
1 Blake null
2 Jake null
6 Scott 2
8 Jack 2
3 Clark null
5 Martin 3
4 Smith null
7 Scott 4
And is there a way to look up the team when a staff is searched?
Search: "Scott"
Returns:
Staff Name Mgr
2 Jake null
6 Scott 2
8 Jack 2
http://rextester.com/OAREI7219 is solution
CREATE TABLE Managers (
MgrID int ,
EmpID int
)
CREATE TABLE Staff (
EmpID int,
name nvarchar(50)
)
Query is ;
SELECT
s.EmpID AS Staff,
s.name AS Name,
m.MgrID
FROM Staff s LEFT JOIN Managers m ON s.EmpID = m.EmpID ;
GO
Assuming that you have:
a table "staff" with all the people in the company. For clarity I will rename the "Staff" column to "id".
a many to many table "staff_manager" to link employees with their managers. For clarity I will rename the "Mgr" column to "manager_id" and the "Emp" to "employee_id".
all tables named lowercase and plural.
You may do:
SELECT employees.id, employees.name, managers.id, managers.name
FROM staff as employees
LEFT JOIN employee_managers ON (employee_managers.employee_id = employees.id)
LEFT JOIN staff as managers ON (managers.id = employee_managers.manager_id)
for the second query you add a where clause to the above query:
WHERE managers.name = "Scott" OR employees.name = "Scott"
NOTE: If you may change the model of your database, I would suggest to
set a UNIQUE constrain on the employee_id of the staff_managers table,
so that one employee can have ONLY ONE manager.
To get All Employees with their managers. Try
Select staff.Id,Staff.name,managers.mgr
From staff left join managers on staf.id=managers.emp
To search about employee and get his team with the manager also. Try
— Search: 'scott'
Select staff.Id,Staff.name,managers.mgr
From staff left join managers on staf.id=managers.emp
Where managers.mgr =(select t.mgr from managers as t where t.emp='scott')
Union all
Select staff.Id,Staff.name,managers.mgr
From managers left join staff on staf.id=managers.mgr
Where managers.emp='scott'
I have two tables: employee and dependent
Structure
- Table employee
Name Null? Type
EMPLOYEEID NOT NULL NUMBER(3)
LNAME NOT NULL VARCHAR2(15)
FNAME NOT NULL VARCHAR2(15)
POSITIONID NUMBER(1)
SUPERVISOR NUMBER(3)
HIREDATE DATE
SALARY NUMBER(6)
COMMISSION NUMBER(5)
DEPTID NUMBER(2)
QUALID NUMBER(1)
- Table Dependent
Name Null? Type
EMPLOYEEID NOT NULL NUMBER(3)
DEPENDENTID NOT NULL NUMBER(1)
DEPDOB NOT NULL DATE
RELATION NOT NULL VARCHAR2(8)
Data
- Table employee
EMPLOYEEID LNAME FNAME POSITIONID SUPERVISOR HIREDATE SALARY COMMISSION DEPTID QUALID
111 Smith John 1 15/04/60 265000 35000 10 1
246 Houston Larry 2 111 19/05/67 150000 10000 40 2
123 Roberts Sandi 2 111 02/12/91 75000 10 2
543 Dev Derek 2 111 15/03/95 80000 20000 20 1
433 McCall Alex 3 543 10/05/97 66500 20 4
135 Garner Stanley 2 111 29/02/96 45000 5000 30 5
200 Shaw Jinku 5 135 03/01/00 24500 3000 30
222 Chen Sunny 4 123 15/08/99 35000 10 3
- Table Dependent
EMPLOYEEID DEPENDENTID DEPDOB RELATION
543 1 28/09/58 Spouse
543 2 14/10/88 Son
200 1 10/06/76 Spouse
222 1 04/02/75 Spouse
222 2 23/08/97 Son
222 3 10/07/99 Daughter
111 1 12/12/45 Spouse
And I have two employees: One employee has one child, and the other has two children. I got it with the following query:
Query
SELECT employee.employeid, lname, fname, salary, dependent.relation
FROM employee INNER JOIN dependent
ON employee.employeeid = dependent.employeeid
WHERE dependent.relation = 'Daughter' OR dependent.relation = 'Son';
Result
EMPLOYEEID LNAME FNAME SALARY RELATION
543 Dev Derek 80000 Son
222 Chen Sunny 35000 Son
222 Chen Sunny 35000 Daughter
And my homework is increase the salary $ 100 per child, and I tried with the following code:
UPDATE employee
SET SALARY = salary + 100
WHERE employee.employeeid IN (
SELECT employee.EMPLOYEEID FROM employee INNER JOIN dependent
ON employee.employeeid = dependent.employeeid
WHERE dependent.relation = 'Daughter' OR dependent.relation = 'Son' );
But, i don´t get the expect result. The employee "Chen" has two children, but his salary only increase once, no twice. Her final salary is $ 35100, no $ 35200.
Can anybody help me?
I can't test on Oracle version 10, but this should work fine:
Well, apparently, it doesn't work in Oracle 10 (though it does work correctly in Oracle 12). I added an alternative at the bottom of the post using merge that should work correctly.
update (
select e.salary,
d.childcnt * 100 as increase
from employee e
join (select d.employeeid, count(*) as childcnt
from dependent d
where d.relation in ('Son', 'Daughter')
group by d.employeeid) d
on d.employeeid = e.employeeid
) set salary = salary + increase
Here is another way of achieving the same thing using the merge command. This should work correctly in Oracle 10:
merge into employee dest
using (
select employeeid,
count(*) * 100 as increase
from dependent d
where relation in ('Son', 'Daughter')
group by employeeid
) src
on (src.employeeid = dest.employeeid)
when matched then
update set dest.salary = dest.salary + src.increase
How would do the following in SQL
"select dept names who have more than 2 employees whose salary is greater than 1000" ?
DeptId DeptName
------ --------
1 one
2 two
3 three
EmpId DeptId Salary
----- ------ ------
121 1 2000
122 1 2000
123 1 5000
124 1 4000
131 2 2000
132 2 6000
133 2 1000
134 2 1000
125 3 1000
126 3 20000
RESULT: one
How about something like this?
SELECT D.DeptName FROM
Department D WHERE (SELECT COUNT(*)
FROM Employee E
WHERE E.DeptID = D.DeptID AND
E.Salary > 1000) > 2
SELECT DEPTNAME
FROM(SELECT D.DEPTNAME,COUNT(EMPID) AS TOTEMP
FROM DEPT AS D,EMPLOYEE AS E
WHERE D.DEPTID=E.DEPTID AND SALARY>1000
GROUP BY D.DEPTID
)
WHERE TOTEMP>2;
select min(DEPARTMENT.DeptName) as deptname
from DEPARTMENT
inner join employee on
DEPARTMENT.DeptId = employee.DeptId
where Salary > 1000
group by (EmpId) having count(EmpId) > =2
hope this helps
select DeptName from DEPARTMENT inner join EMPLOYEE using (DeptId) where Salary>1000 group by DeptName having count(*)>2
select D.DeptName from [Department] D where D.DeptID in
(
select E.DeptId from [Employee] E
where E.Salary > 1000
group by E.DeptId
having count(*) > 2
)
select deptname from dept_1
where exists
(
SELECT DeptId,COUNT(*)
FROM emp_1
where salary>1000
and emp_1.deptid=dept_1.deptid
GROUP BY DeptId
having count(*)>2)
1:list name of all employee who earn more than RS.100000 in a year.
2:give the name of employee who earn heads the department where employee with employee I.D
My main advice would be to steer clear of the HAVING clause (see below):
WITH HighEarners AS
( SELECT EmpId, DeptId
FROM EMPLOYEE
WHERE Salary > 1000 ),
DeptmentHighEarnerTallies AS
( SELECT DeptId, COUNT(*) AS HighEarnerTally
FROM HighEarners
GROUP
BY DeptId )
SELECT DeptName
FROM DEPARTMENT NATURAL JOIN DeptmentHighEarnerTallies
WHERE HighEarnerTally > 2;
The very early SQL implementations lacked derived tables and HAVING was a workaround for one of its most obvious drawbacks (how to select on the result of a set function from the SELECT clause). Once derived tables had become a thing, the need for HAVING went away. Sadly, HAVING itself didn't go away (and never will) because nothing is ever removed from standard SQL. There is no need to learn HAVING and I encourage fledgling coders to avoid using this historical hangover.