This question already has answers here:
Oracle show all employees with greater than average salary of their department
(4 answers)
Closed 3 years ago.
I'm trying to display the employeeno#, employee name, department, and salary for all employees who earn more than the average salary in their own department.
I've only tried this:
Select empno, ename, deptno,sal As Salary
From emp
Where sal >(SELECT AVG (sal) FROM emp);
For this structure, you can use a correlation condition. And that requires introducing table aliases:
select e.empno, e.ename, e.deptno, e.sal As Salary
from emp e
where e.sal > (select avg(e2.sal) from emp e2 where e2.deptno = e.deptno);
It is more efficient to join the table to the average salaries of each deptno under the condition that the salary of the employee is more than the average:
select e.empno, e.ename, e.deptno, e.sal
from emp e inner join (
select deptno, avg(sal) sal from emp group by deptno
) t
on t.deptno = e.deptno and t.sal < e.sal
In Oracle Database the most efficient query would be using analytic functions:
select empno, ename, deptno, sal from
(select emp.*, AVG(sal) over (partition by deptno) avgsal from emp)
where sal > avgsal;
Just one table scan and filtering on the view.
Related
We have table emp containing columns empno, ename, job, mgr, hiredate, sal, comm, deptno and table dept containing columns deptno, dname, loc
We're selecting the dname where the sum of employee salaries is greater than the average sums of salaries from all departments
I'm unfamiliar with using multiple SELECTs in a single query, this is what I try:
SELECT d.dname FROM emp e
JOIN dept d ON e.deptno = d.deptno
GROUP BY d.deptno HAVING SUM(e.sal) >
(SELECT AVG(sal) FROM emp
GROUP BY deptno)
Gives an error for having multiples lines returned by the second select, when I experimented I did not find a way to match the right single lines
How do you select the right dnames?
You can use avg()over() window function to get the average of department wise salary sum. Then use this in cte and just select the departments with sum of salary greater than the average of sums.
Schema and inert statements:
create table emp(empno varchar(100), ename varchar(100), job varchar(100), mgr varchar(100), hiredate date, sal int, comm int, deptno varchar(100));
insert into emp values('e01','Adam',null,null,'01-01-2021',10000,null,'D01');
insert into emp values('e02','Zaid',null,null,'01-01-2021',12000,null,'D01');
insert into emp values('e03','Noor',null,null,'01-01-2021',20000,null,'D02');
insert into emp values('e04','Seth',null,null,'01-01-2021',12000,null,'D03');
create table dept (deptno varchar(100),dname varchar(100));
insert into dept values('D01','HR');
insert into dept values('D02','IT');
insert into dept values('D03','Sales');
Query:
with cte as
(
SELECT deptno, SUM(sal) AS salary_sum ,avg(sum(sal))over() salary_average
FROM emp
GROUP BY deptno
)
select *
from cte c inner join dept d
on c.deptno=d.deptno
where salary_sum>salary_average
Output:
deptno
salary_sum
salary_average
deptno
dname
D01
22000
18000.000000000000
D01
HR
D02
20000
18000.000000000000
D02
IT
db<>fiddle here
Your subquery returns the average salary per department instead of the average of the sum of salaries:
SELECT d.dname FROM emp e
JOIN dept d ON e.deptno = d.deptno
GROUP BY d.deptno HAVING SUM(e.sal) >
(SELECT AVG(s)
FROM (SELECT SUM(sal) AS s
FROM emp
GROUP BY deptno) t
)
I have a table Employee with those columns
empid, empname, job, hiredate, sal, comm, deptno
I want to verify if this is correct:
Number of employees in each department
How many people there are in each type of job in each department
Display the department and number of employees in department with fewer than 6 employees
Find the employee name and its salary who is earning maximum salary in dept 20
Here is what I have tried:
Query #1:
select DEPTNO, count(*) AS NO_OF_PERSONS
from EMP
group by DEPTNO;
Query #2:
select job, count(*) AS NO_OF_PERSONS
from EMP
group by job;
Query #3:
update EMPLOYEE
set sal = sal + 1000
where com > 2500;
And I am unable to do the 4th part.
I hope that below queries will help you.
no of employees in each dept?
SELECT DEPTNO,
count(*) AS NO_OF_PERSONS
FROM EMP
GROUP BY DEPTNO;
how many people are there in each type of job in each department?
SELECT job,
deptno,
count(*) AS NO_OF_PERSONS
FROM EMP
GROUP BY job,
deptno;
display the department and no of employees in department with fewer than 6 employee.
SELECT deptno,
count(*)
FROM emp
GROUP BY deptno
HAVING count(*) < 6;
find the employee name and its salary who is earning maximum salary in dept 20.
SELECT Max(salary_amount),
empid
FROM EMP
WHERE deptno = 20
GROUP BY empid;
You can start learning Basic SQL here
select e1.name, e1.sal
from EMP e1
where e1.DEPTNO = 20
and not exists(select *
from EMP e2
where e2.DEPTNO = 20
and e2.sal > e1.sal);
Practicing some SQL, we have to get the name of the employees whose salary is the greatest of his department. But if in any department there were more than one employer with the greatest salary, we would not have to consider that department.
We got the first part but not the second one (because there are two employees with the same greatest salary (3,000) in the same department (20)).
This is what we did:
SQL> SELECT ename, sal, deptno FROM emp a
WHERE sal >= ALL (SELECT sal FROM emp WHERE deptno=a.deptno)
ORDER BY sal;
And this is what we got:
ENAME SAL DEPTNO
---------- ------- ------
BLAKE 2,850 30
FORD 3,000 20
SCOTT 3,000 20
KING 5,000 10
4 filas seleccionadas.
Any help will be useful, thank you!
SELECT ename, sal, deptno
FROM emp a
WHERE not exists (
SELECT *
FROM emp
WHERE deptno=a.deptno
and sal >= a.sal
and ename != a.ename)
ORDER BY sal;
with cte as
( SELECT ename, sal, deptno
, row_number() over (partition by deptno order by sal desc) as rn
FROM emp
)
select ename, sal, deptno from cte where rn = 1
except
select ename, sal, deptno from cte where rn = 2
order by sal
if this does not work in oracle - it used to be also tagged mssql
You can have what you need with some analytic functions:
select ename,
deptno,
sal
from (
select ename,
deptno,
sal,
row_number() over(partition by deptno order by sal desc) AS num,
count(1) over(partition by deptno, sal) AS count
from emp
)
where num = 1
and count = 1
The inner query orders by salary and counts the number of employees with the same salary in the same department; the outer one simply filters for employees with the maximum salary, where only one employee has that salary in the department.
With a different approach, simply modifying your query, you can try:
SELECT ename, sal, deptno FROM emp a
WHERE sal >= ALL (SELECT sal FROM emp WHERE deptno=a.deptno)
and (select count(1) from emp b where a.deptno = b.deptno and a.sal = b.sal) = 1
The first way gives better performance, with a single table scan, while the second one needs a nested query, thus being less efficient
try to use GROUP BY column_name`, it will show the record without duplicate.
I'm having an assignment for my sql class which i can't seem to figure out. This is the description of the select wanted:
Show all employees of which the salary is higher than the average of the colleagues in their department, only for the departments with at least 4 employees.
I've been able to find parts of the query like
select ename
from emp
where sal > any (select avg(sal)
from emp
group by
deptno);
to get the names of the employees which earn more than the avg.
or
select count(deptno)
from emp
group by
deptno having count(deptno) > 4;
to getthe number of employees in each department.
But somehow it doesn't work linking them together. Maybe someone can help me shine a light on this on.
Just put your second query in with an AND clause:
select ename
from emp
where sal > any (select avg(sal)
from emp
group by
deptno)
and deptno in (select deptno
from emp
group by
deptno having count(deptno) > 4);
You can use Having Clause in Conjunction with Group By
select ename
from emp
where sal > any (select avg(sal)
from emp
group by
deptno)
having count(*)>4;
select ename
from (
select deptno, count(deptno)
from emp
group by deptno
having count(deptno) > 4) valid_depts join emp ON emp.deptno=valid_depts.deptno
where sal > any (select avg(sal)
from emp
group deptno);
There are 2 tables available
EMP(empname PK, empno, sal, comm, deptno, hiredate, job, mgr)
DEPT(depnto, dname, loc)
The queries are
a)Display the ename and dname who is earning the first highest salary
They have given a statement this has to be done using only subqueries and Join
So i started like this:
select A.ename, B.dname from emp A, dept B where A.deptno=B.deptno
and i tried various perm&comb, but i couldn't get the join statement...
This is not a homework problem, i am just trying to solve the exercise problem given in my textbook..Thanks in advance
To get the record with the max salary I've Ordered by e.sal DESC. This will order the records in terms of salary, with the highest at the top (DESC = Descending, and therefore highest-lowest).
Then I've used TOP 1 to only return 1 record.
To get the dname I've joined the tables relating the 2 deptno columns.
SELECT TOP 1 e.empname
,d.dname
FROM [EMP] e
JOIN [DEPT] d ON d.deptno=e.deptno
ORDER BY e.sal DESC
I hope this helps
You can try following query:
SELECT emp.ename,dept.dname FROM emp
JOIN dept ON emp.deptno=dept.deptno
WHERE emp.sal=(SELECT MAX(sal) FROM emp)