How do I combine two working SELECT queries into one query? - sql

I have two queries which work independently of one another;
SELECT e.employee_id,
e.first_name,
e.last_name,
e.job_id,
e.salary,
e.commission_pct, e.manager_id,
e.department_id,
j.start_date,
j.end_date
FROM hr.employees e
LEFT OUTER JOIN hr.job_history j
ON e.employee_id = j.employee_id
WHERE commission_pct IS NULL
This first one recalls the information from two different tables, hr.employees and hr.job_history.
Here is the second;
SELECT e.employee_id,
e.last_name,
m.employee_id "MgrNo",
m.last_name "MgrName"
FROM hr.employees e
INNER JOIN hr.employees m ON e.manager_id=m.employee_id
This is to link employee_id with manager_id to display each employee's manager surname. However, when I try to include the two together I keep getting an error telling me I have an invalid prefix. Any ideas?

"I keep getting an error telling me I have an invalid prefix."
That is a typo. We can't spot it in a version of the query you haven't posted. But basically you just need another join in the first query like this:
SELECT e.employee_id,
e.first_name,
e.last_name,
e.job_id,
e.salary,
e.commission_pct,
m.employee_id "MgrNo",
m.last_name "MgrName",
e.department_id,
j.start_date,
j.end_date
FROM hr.employees e
LEFT OUTER JOIN hr.job_history j
ON e.employee_id = j.employee_id
LEFT OUTER JOIN hr.employees m
ON m.employee_id = e.manager_id
WHERE e.commission_pct IS NULL
I suggest using an outer join, because normally not every employee has a manager (depending on how you have implemented the hierarchy).

Try:
WITH temptable AS (
SELECT e.employee_id, e.last_name, m.employee_id "MgrNo", m.last_name "MgrName"
FROM hr.employees e
INNER JOIN hr.employees m ON
e.manager_id=m.employee_id)
SELECT e.employee_id, e.first_name, e.last_name, e.job_id, e.salary, e.commission_pct, e.manager_id, e.department_id, j.start_date, j.end_date, t.MgrNo, t.MgrName
FROM hr.employees e
LEFT OUTER JOIN hr.job_history j ON e.employee_id = j.employee_id
LEFT JOIN temptable t ON t.employee_id = e.employee_id
WHERE commission_pct IS NULL
This uses one as a subquery then joins its key on your first query's key.

It would seem that you are attempting to create a query which will produce employee salary/commission history with their manager info. You can combine the queries like this:
SELECT e.employee_id, e.first_name, e.last_name, e.job_id, e.salary,
commission_pct, e.manager_id, e.department_id, j.start_date, j.end_date,
m.employee_id "MgrNo", m.last_name "MgrName"
FROM hr.employees e
INNER JOIN hr.employees m ON e.manager_id=m.employee_id
LEFT OUTER JOIN hr.job_history j ON e.employee_id = j.employee_id
WHERE commission_pct IS NULL

Related

Oracle: range of standard deviation of salary in correlated subquery

I am using an Oracle Developer Database and I have the two tables, Employees and Departments :
I am supposed to find (using a correlated subquery) for each department all the employees, which have a salary within the range of the salary-standard deviation of every single department.
This is what I have tried so far:
SELECT d.department_name, e.employee_id, e.last_name, AVG(e.salary), e.salary
FROM hr.employees e
JOIN hr.departments d
on e.department_id = d.department_id
WHERE e.salary IN
(SELECT salary
FROM hr.employees
WHERE salary >
(SELECT ROUND(AVG(e.salary)-STDDEV(e.salary),2)
FROM hr.employees) AND salary < (SELECT ROUND(AVG(e.salary) + STDDEV(e.salary),2) FROM hr.employees)
GROUP BY d.department_name,
e.employee_id, e.last_name, e.salary;
Even though this query has the correct syntax, it does not show any result.
This other (partial) approach works but how can I query at the same time the employee table?
SELECT d.department_name, e.department_id, ROUND(AVG(e.salary) + STDDEV(e.salary), 2)
AS standard_deviation_max,
ROUND(AVG(e.salary) - STDDEV(e.salary), 2)
AS standard_deviation_min
FROM hr.employees e
JOIN hr.departments d
on e.department_id = d.department_id
GROUP BY department_name, e.department_id;
Since I am new to SQL, I would really appreciate any hint. Thank you in advance
You can use your query to find the employee details and then correlate the salary to the average ± the standard deviation:
SELECT d.department_name,
e.employee_id,
e.last_name,
e.salary
FROM hr.employees e
JOIN hr.departments d
on e.department_id = d.department_id
WHERE EXISTS (
SELECT 1
FROM hr.employees x
HAVING e.salary BETWEEN AVG(e.salary) + STDDEV(e.salary)
AND AVG(e.salary) + STDDEV(e.salary)
);
or, you can use analytic functions:
SELECT department_name,
employee_id,
last_name,
salary
FROM (
SELECT d.department_name,
e.employee_id,
e.last_name,
e.salary,
AVG(e.salary) OVER () AS avg_salary,
STDDEV(e.salary) OVER () AS stddev_salary
FROM hr.employees e
JOIN hr.departments d
on e.department_id = d.department_id
)
WHERE salary BETWEEN avg_salary - stddev_salary
AND avg_salary + stddev_salary;

Some results disappear after GROUP BY

So I have a table of Employment and I select everyone whose ID is repeated,
SELECT e.emp_id, e.first_name, e.last_name
FROM Employment Emp
JOIN Employee e
ON e.emp_id = Emp.emp_id
JOIN Department d
ON Emp.dept_id = d.dept_id
GROUP BY e.emp_id, e.first_name, e.last_name
HAVING count(Emp.emp_id) > 1
But after I use d.name (department name) in SELECT and GROUP BY some employees disappear.
SELECT e.emp_id, e.first_name, e.last_name, d.name
FROM Employment Emp
JOIN Employee e
ON e.emp_id = Emp.emp_id
JOIN Department d
ON Emp.dept_id = d.dept_id
GROUP BY e.emp_id, e.first_name, e.last_name,d.name
HAVING count(Emp.emp_id) > 1
I want to get all employee departments who are in first table.
You can use a window function instead:
SELECT ed.*
FROM (SELECT e.emp_id, e.first_name, e.last_name, d.name,
COUNT(*) OVER (PARTITION BY e.emp_id, e.first_name, e.last_name) as cnt
FROM Employment Emp JOIN
Employee e
ON e.emp_id = Emp.emp_id JOIN
Department d
ON Emp.dept_id = d.dept_id
) ed
WHERE cnt > 1
ORDER BY ed.emp_id, ed.first_name, ed.last_name;
Your two queries ask different questions. The second count() is more granulated (+ by department.name) and looks like no one of "disappeard" persons is employed at the same department twice or more.

i am not getting error missing keyword in my code

select e.department_id,e.salary,d.department_name
from employees e
join departments d
on d.department_id=e.department_id
inner join
(
select department_id,max(salary) as max_sal from employees
group by department_id
) as t
on e.department_id=t.department_id
where e.salary =t.max_sal;
Oracle does not support as for table aliases, so you can try:
select e.department_id, e.salary, d.department_name
from employees e join
departments d
on d.department_id = e.department_id inner join
(select department_id, max(salary) as max_sal
from employees
group by department_id
) t
on e.department_id = t.department_id
where e.salary = t.max_sal;
Of course, this would be better written using window functions, but this answers the question that you asked.

How to debug this SQL query?

I run this code and it does not work (I am expecting a result set but I do not get one):
select e.employee_id,e.first_name,e.last_name,e.salary,d.department_name,l.city from employees e
join departments d on e.department_id = d.department_id
join locations l on l.location_id = d.location_id
where e.salary = select max(salary) from employees where hire_date between '2002-01-01' and '2003-12-31';
however if I run the queries
select max(salary) from employees where hire_date between '2002-01-01' and '2003-12-31';
and
select e.employee_id,e.first_name,e.last_name,e.salary,d.department_name,l.city from employees e
join departments d on e.department_id = d.department_id
join locations l on l.location_id = d.location_id
where e.salary = 24000.00
they run fine. max(salary) from the second query is 24000.00.
This is the website where I am trying to practice (question no 34)
https://www.w3resource.com/sql-exercises/sql-subqueries-exercises.php
You are missing parenthesis for sub-query
SELECT e.employee_id,
e.first_name,
e.last_name,
e.salary,
d.department_name,
l.city
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
JOIN locations l
ON l.location_id = d.location_id
WHERE e.salary = (SELECT Max(salary)
FROM employees
WHERE hire_date BETWEEN '2002-01-01' AND '2003-12-31');
Please use "IN" clause instead of "=" while filtering using a Subquery
SELECT e.employee_id,
e.first_name,
e.last_name,
e.salary,
d.department_name,
l.city
FROM employees e
JOIN departments d
ON e.department_id = d.department_id
JOIN locations l
ON l.location_id = d.location_id
WHERE e.salary IN (SELECT Max(salary)
FROM employees
WHERE hire_date BETWEEN '2002-01-01' AND '2003-12-31');

How can I show in a single SQL query: What departments don't have any employees and what employees don't have a department (Oracle SQL)?

I've been trying to figure this out for a while and still no luck. Would I combine the following with a 'is null'?
select distinct
e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
from employees e
join departments d on (e.department_id = d.department_id)
Example based on Joe's comment
select distinct
e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
from employees e
full outer join departments d on (e.department_id = d.department_id)
where e.department_id is null or d.department_id is null
Or this way with union
select distinct
e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
from employees e
left outer join departments d on (e.department_id = d.department_id)
where d.department_id is null
union
select distinct
e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
from employees e
right outer join departments d on (e.department_id = d.department_id)
where e.department_id is null