I have one employee table. Please find below the table structure along with data.
I want to find the maximum salary and minimum salary along with employee name.
expected output will be:
To find out the maximum salary along with employee name I have written this query:
SELECT name,salary FROM employee where salary
= (select max(salary) from employee);
And to find out the minimum salary along with employee name I have written this query:
SELECT name,salary FROM employee where salary
= (select min(salary) from employee);
But I am unable to merge these two queries.
Can someone please guide me to build the SQL query which will return maximum salary and minimum salary along with employee name?
Here is one way, using RANK
. This answer makes one pass in a CTE to find the lowest and highest ranked salaries in the employee table. Then, it subqueries only once to retrieve the full matching records.
WITH cte AS (
SELECT NAME, SALARY,
RANK() OVER (ORDER BY SALARY) rnk_min,
RANK() OVER (ORDER BY SALARY DESC) rnk_max
FROM employee
)
SELECT NAME, SALARY
FROM cte
WHERE rnk_min = 1 OR rnk_max = 1
ORDER BY SALARY;
If you want it all returned in a single record, do this:
WITH t1 AS (
SELECT name, salary FROM employee where salary
= (select max(salary) from employee) ),
t2 AS (
SELECT name, salary FROM employee where salary
= (select min(salary) from employee) )
SELECT
t1.name AS MAX_NAME, t1.salaray AS MAX_SALARY, t2.name AS MIN_NAME, t2.salaray AS MIN_SALARY
FROM t1 LEFT JOIN t2 ON 1=1
This puts both your queries into Common Table Expressions (CTEs, essentially act like their own tables you can query against). Then, it joins them on the arbitrarily true 1=1. Then you just select your four values.
You could use union all
or or
:
SELECT e.name, e.salary
FROM employee e
WHERE e.salary = (SELECT MAX(e2.salary) FROM employee e2) OR
e.salary = (SELECT MIN(e2.salary) FROM employee e2);
You can also use self-join alike
query logic
with Employee(name, salary) as
(
select 'Rick',3000 from dual union all
select 'John',4000 from dual union all
select 'Shane',3000 from dual union all
select 'Peter',5000 from dual union all
select 'Jackob',7000 from dual
)
select name, salary
from Employee
join ( select max(salary) as max_sal,
min(salary) as min_sal
from Employee )
on salary in ( min_sal, max_sal )
group by name, salary
order by salary desc, name;
NAME SALARY
------ -------
Jackob 7000
Rick 3000
Shane 3000
If you code as you speak you get for get all employees with salary [ IN
] min(salary) or max(salary) :
SELECT e.name, e.salary
FROM employee e
WHERE e.salary in (
select min(salary) sal from employee
union
select max(salary) from employee);
The important thing is to define the index on salary
create index employee_Idx on employee(salary);
The query makes two index access to get the min and max values - lines 7 and 9 in the plan below. Than using this selected values a NESTED LOOPS
is performed with index access on salary
and a table access by ROWID.
Note that this optimization pressumes that there are only few rows with the extreme salaries (which is normaly the case - at least for the MAX
;)
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 66 | 6 (34)| 00:00:01 |
| 1 | NESTED LOOPS | | 3 | 66 | 6 (34)| 00:00:01 |
| 2 | NESTED LOOPS | | 3 | 66 | 6 (34)| 00:00:01 |
| 3 | VIEW | VW_NSO_1 | 2 | 26 | 4 (50)| 00:00:01 |
| 4 | SORT UNIQUE | | 2 | 6 | 4 (50)| 00:00:01 |
| 5 | UNION-ALL | | | | | |
| 6 | SORT AGGREGATE | | 1 | 3 | 2 (50)| 00:00:01 |
| 7 | INDEX FULL SCAN (MIN/MAX)| EMPLOYEE_IDX | 1 | 3 | 1 (0)| 00:00:01 |
| 8 | SORT AGGREGATE | | 1 | 3 | 2 (50)| 00:00:01 |
| 9 | INDEX FULL SCAN (MIN/MAX)| EMPLOYEE_IDX | 1 | 3 | 1 (0)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | EMPLOYEE_IDX | 1 | | 0 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | EMPLOYEE | 1 | 9 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
10 - access("E"."SALARY"="SAL")
Tried with postgresql
select sub.emp_name, sub.salary
from (
select *,
dense_rank() over (order by salary) as my_rank,
dense_rank() over (order by salary desc) as my_rank_desc
from employee ) sub
where my_rank = 1 or my_rank_desc = 1
order by salary
select first_name,last_name, role,salary from emp_record_table
where salary in(
select max(salary) from emp_record_table group by role
union
select min(salary) from emp_record_table group by role ) ;
o/p
Arthur Black PRESIDENT 16500
Eric Hoffman LEAD DATA SCIENTIST 8500
William Butler LEAD DATA SCIENTIST 9000
Dianna Wilson SENIOR DATA SCIENTIST 5500
Dorothy Wilson SENIOR DATA SCIENTIST 7700
Steve Hoffman ASSOCIATE DATA SCIENTIST 5000
Pete Allen MANAGER 11000
David Smith ASSOCIATE DATA SCIENTIST 4000
Chad Wilson ASSOCIATE DATA SCIENTIST 5000
Tracy Norris MANAGER 8500
Katrina Allen JUNIOR DATA SCIENTIST 3000
Jenifer Jhones JUNIOR DATA SCIENTIST 2800
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.