How to debug this SQL query? - sql

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');

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;

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.

I am trying retrieving data from more than one table using joins in SQL Developer but I get an error ORA-00933: SQL command not properly ended

select
e.first_name, e.last_name,
e.first_name || e.last_name "Name",
d.department_name, d.manager_id,
l.country_id, l.city
from
employees e
join
departments d on e.department_id = d.department_id
join
locations l on d.location_id = l.location_id
where
d.manager_id = &d.manager_id;
Try this and check if it help you ;)
select
e.first_name, e.last_name,
concat(e.first_name, ' ', e.last_name) "Name",
d.department_name, d.manager_id,
l.country_id, l.city
from
employees e
join
departments d on e.department_id = d.department_id
join
locations l on d.location_id = l.location_id
where
d.manager_id = &d.manager_id;

Select EVERY department and number of employees with salary higher than 10000

I need to select every department name and number of employees earning 10000 or more. That's my code.
SELECT d.department_name, COUNT(e.employee_id)
FROM hr.employees e
JOIN hr.departments d ON d.department_id=e.department_id WHERE e.salary > 10000
GROUP BY d.department_name;
It shows only departments which contains employees earning 10000 but I also need rest of departments with number 0 or - in column COUNT(e.employee_id). Can you help me?
You can do conditional aggregation. The idea is to not put the condition on employee salary in the join, but instead it in a conditional sum:
select
d.department_name,
sum(case when e.salary > 10000 then 1 else 0 end) cnt_high_salaries
from hr.department d
inner join hr.employee e on d.department_id = e.department_id
group by d.department_id, d.department_name
I think you just need outer join in your original query.
SELECT d.department_name,
COUNT(e.employee_id)
FROM hr.departments d
LEFT JOIN hr.employees e
ON d.department_id=e.department_id
and e.salary > 10000
GROUP BY d.department_name;
Is this what you are looking for?
SELECT d.department_name, COUNT(e.employee_id) FROM hr.employees e
JOIN hr.departments d ON d.department_id=e.department_id WHERE d.department_id in
(SELECT distinct e.department_id from employees e WHERE e.salary > 10000)
GROUP BY d.department_name;

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