Was asked in an interview a traditional question of self join with manager and employee.
I was confused as interviewer asked me to display the columns as EmployeeName, Manager Name.
Please advice how does the conditions in where clause effects the selected columns. As I wasn't able to get the required order.
The trick here is that every manager is also an employee, so you can join the table on itself, and use one side of the join for the employee details and the other for the manager's details:
SELECT e.eployee_name AS "employee name", m.employee_name AS "manager name"
FROM employee e
JOIN employee m ON e.manager_id = m.employee_id
You can use the connect by query as following:
select employee_name, prior employee_name
from employees
connect by prior employee_id = manager_id
start with manager_id is null
If you want to use join then you must do outer join as following:
Select e.employee_name, m.employee_name
From employees e left join employees m
On e.employee_id = m.employee_id
Left outer join will make sure that all the employees will exists in the result as the employee who is the top manager will have null manager_id and inner join will exclude that employee from the result.
Cheers!!
Related
Im trying to understand inner join correct use but im having trouble when I have to call more than 2 tables, im using oracle HR schema for tests, so for example im trying this query:
select emps.employee_id,
emps.first_name,
dep.department_name,
dep.department_id,
jh.job_id
from employees emps
inner join departments dep
on emps.department_id = dep.department_id
inner join job_history jh
on dep.department_id = jh.department_id;
which shows the following result:
I know its wrong because first its showing duplicate rows, and second if I run this query
select * from job_history where employee_id = 100;
It shows no results which means that employee 100 (steven) shouldnt be appearing in the results of the first query, I expect first query to show me the results of data that is on employees and also on department and also on job_history which have in common the department_id
HR (human resources schema):
Can anyone help me, what im missing, why it shows duplicate rows?
The job_history table has 3 foreign keys:
employee_id
job_id
department_id
Your INNER JOIN only joins on the DEPARTMENT_ID so you are matching an employee to the job history for any jobs that occurred for their department but not necessarily jobs specific to that employee. Instead, you probably want to join on either the employee_id or the combination of employee_id and department_id.
So, if you want the jobs history for that employee for any department:
select emps.employee_id,
emps.first_name,
dep.department_name,
dep.department_id,
jh.job_id
from employees emps
inner join departments dep
on ( emps.department_id = dep.department_id )
inner join job_history jh
on ( emps.employee_id = jh.employee_id );
Or, if you want the job history for that employee within that department:
select emps.employee_id,
emps.first_name,
dep.department_name,
dep.department_id,
jh.job_id
from employees emps
inner join departments dep
on ( emps.department_id = dep.department_id )
inner join job_history jh
on ( emps.employee_id = jh.employee_id
and emps.department_id = jh.department_id );
SELECT m.employee_id, m.first_name, m.last_name
FROM employees e
JOIN employees m ON (e.manager_id = m.employee_id)
JOIN job_history USING (employee_id)
WHERE job_id LIKE 'A%';
Which table does this EMPLOYEE_ID belong to? Apply table aliases to all columns, always.
SELECT m.employee_id, m.first_name, m.last_name
FROM employees e
JOIN employees m
ON (e.manager_id = m.employee_id)
JOIN job_history
USING (employee_id) --> this?
WHERE job_id LIKE 'A%'; --> ... and this would also benefit from an alias
Qualify all column names in the query. When you use using, you do not need to qualify the names of the keys used for the join.
Then, using uses all matching column names. I think you want to be specific about which tables the columns are coming from:
SELECT m.employee_id, m.first_name, m.last_name
FROM employees e JOIN
employees m
ON e.manager_id = m.employee_id JOIN
job_history jh
ON jh.employee_id = ?.employee_id -- Is this for the manager or the employee?
WHERE jf.job_id LIKE 'A%';
I wondering is what I am doing right.
select distinct
Departments.Department_No, Departments.Department_Name
from
Departments
join
Employees on Departments.Department_No = Employees.Department_No
join
Jobs on Jobs.Job_ID = Employees.Job_ID
where
Departments.Department_No not in (select distinct Department_No
from Employees
where Employees.Job_ID like '%SA_REP%');
You want to display distinct values of Department Number and Department Name
You join Employees table with Department on Department Number
You join Jobs table with Employees on Job ID
You filter the result by excluding those Department Numbers of the entire Employee table that have a Job ID matching the pattern %SA_REP%
In my opinion you don't need
the join with the Jobs table
the join with the Employees table
you could maybe see if one of the other users' suggestions can bring performance improvement
SELECT DISTINCT departments.department_no,
departments.department_name
FROM departments
WHERE departments.department_no NOT IN (SELECT DISTINCT department_no
FROM employees
WHERE employees.job_id LIKE '%SA_REP%'
);
You could simply do this using NOT EXISTS instead of using a NOT IN subquery:
SELECT DISTINCT
d.Department_No
,d.Department_Name
FROM Departments d
JOIN Employees e ON d.Department_No = e.Department_No
WHERE NOT EXISTS
(select 1
from Employees e1
where e1.Job_ID like '%SA_REP%'
AND e1.Department_No = e.Department_No);
You can translate where condition without "in".
And you don't need to fetch date from "Jobs" - you don't use it
Select distinct Departments.Department_No, Departments.Department_Name
from Departments
Join Employees on Departments.Department_No = Employees.Department_No
where Employees.Job_ID not like '%SA_REP%';
The goal here is to return the ID, Name, and Manager Name and ID for each Employee. The table does not contain a manager name, only a manager ID for a given employee. The current query works great using an inner join, except that one employee does not have a manager ID (he's the boss), and so none of his information appears. The current query looks like this:
SELECT DISTINCT e.employee_id AS EMPLOYEE_ID,
e.FULL_NAME AS EMPLOYEE_NAME,
m.manager_ID AS REPORTS_TO,
m.FULL_NAME AS MANAGER_NAME
FROM EMPS e
INNER JOIN EMPS m ON e.manager_id = m.employee_id;
How can I include the name and information for this employee despite his lack of a seemingly necessary field? Thanks
If you want to include the employee name when there is no manager do a left join:
SELECT DISTINCT e.employee_id AS EMPLOYEE_ID,
e.FULL_NAME AS EMPLOYEE_NAME,
m.manager_ID AS REPORTS_TO,
m.FULL_NAME AS MANAGER_NAME
FROM EMPS e
LEFT JOIN EMPS m ON e.manager_id = m.employee_id;
if there :
(department) table: (id,name)
(employee) table : (id,dept_id,name)
how to show every department (id,name), then all employees (id,name) in this department under its department.
I'd like it as SQL statment
You need to use JOIN
I believe it's something like this:
SELECT department.id, department.name, employee.id, employee.name
FROM department
LEFT JOIN employee
ON department.id=employee.dept_id
ORDER BY department.id
Since all employees must be present under a particular department at any time, you can do a inner join on both the table with dept_id like
SELECT dept.id, dept.name, emp.id, emp.name
FROM department dept
JOIN employee emp
ON dept.id=emp.dept_id
Simply try this
SELECT D.ID,D.Name,E.ID,E.Name
FROM Department D Left JOIN Employee E ON E.dept_id = D.Id