Как написать SQL-запрос, чтобы найти максимальную и минимальную зарплату вместе с именем сотрудника в Oracle - PullRequest
0 голосов
/ 25 декабря 2018

У меня есть одна таблица сотрудников.Ниже приведена структура таблицы вместе с данными.

enter image description here

Я хочу найти максимальную и минимальную зарплаты вместе с именем сотрудника.

ожидаемый результат будет:

enter image description here

Чтобы узнать максимальную зарплату вместе с именем сотрудника, я написал этот запрос:

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-запрос, который будет возвращать максимальную и минимальную зарплаты вместе с именем сотрудника?

Ответы [ 5 ]

0 голосов
/ 26 декабря 2018

Если вы набираете код, как вы говорите , вы получаете , получаете всех сотрудников с зарплатой [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);

Запрос делает два доступа к индексу для получения значений min и max - строки 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")
0 голосов
/ 25 декабря 2018

Вы также можете использовать 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 demo

0 голосов
/ 25 декабря 2018

Вот один из способов, используя 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;

enter image description here

Демо

0 голосов
/ 25 декабря 2018

Если вы хотите, чтобы все это возвращалось в одной записи, сделайте следующее:

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.Затем вы просто выбираете четыре значения.

0 голосов
/ 25 декабря 2018

Вы можете использовать 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);
...