简体   繁体   中英

How to write SQL query to find max and min salary along with employee name in Oracle

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;

在此输入图像描述

Demo

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

dbfiddle.uk demo

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM