繁体   English   中英

如何编写 SQL 查询以在 Oracle 中查找最高和最低工资以及员工姓名

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

我有一张员工表。 请在下面找到表结构和数据。

在此处输入图像描述

我想找到最高工资和最低工资以及员工姓名。

预计 output 将是:

在此处输入图像描述

为了找出最高薪水和员工姓名,我写了这个查询:

SELECT name,salary FROM  employee where salary
= (select max(salary) from employee);

为了找出最低工资和员工姓名,我写了这个查询:

SELECT name,salary FROM  employee where salary
= (select min(salary) from employee);

但我无法合并这两个查询。

有人可以指导我构建 SQL 查询,该查询将返回最高薪水和最低薪水以及员工姓名吗?

这是一种使用RANK 这个答案在CTE中进行一次通过,以找到员工表中排名最低和排名最高的工资。 然后,它只查询一次子查询以检索完整的匹配记录。

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;

在此输入图像描述

演示

如果您希望将它们全部返回到单个记录中,请执行以下操作:

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

这会将您的查询放入公用表表达式(CTE,基本上就像您可以查询的自己的表一样)。 然后,它将它们连接在任意真的1 = 1上。 然后你只需选择四个值。

你可以使用union all 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);

您还可以使用self-join alike查询逻辑

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演示

如果您按照自己的意思编写代码 ,则可以获得所有员工的工资[ IN ]最低(工资)或最高工资(工资)

SELECT e.name, e.salary
FROM employee e
WHERE e.salary in ( 
  select min(salary) sal from employee 
    union 
  select max(salary) from employee);

重要的是定义薪水指数

 create index  employee_Idx on  employee(salary);

查询进行两次索引访问以获取最小值和最大值 - 下面的计划中的第7行和第9行。 与使用此选定值相比, NESTED LOOPS执行对salary索引访问和ROWID的表访问。

请注意,此优化表明只有少数行具有极高的工资(这通常是这种情况 - 至少对于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")

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

开/关

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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