N зарплата в SQL - PullRequest
       30

N зарплата в SQL

1 голос
/ 20 февраля 2020

Я пытаюсь понять приведенный ниже запрос, как он работает.

SELECT *
FROM Employee Emp1
WHERE (N-1) = (
               SELECT COUNT(DISTINCT(Emp2.Salary))
               FROM Employee Emp2
               WHERE Emp2.Salary > Emp1.Salary
               )

Допустим, у меня есть 5 отличные зарплаты и я хочу получить 3rd наибольшую зарплату. Итак, сначала будет выполняться внутренний запрос, а затем внешний запрос?

Я запутался, как это делается в sql движке. Любопытно узнать. Если значение 3rd больше, чем 3-1 = 2, то необходимо сопоставить 2 с внутренним счетом. Как работает внутренний счет.

Может кто-нибудь объяснить, как это работает ..?

Ответы [ 3 ]

1 голос
/ 20 февраля 2020

Подзапрос является коррелированным подзапросом, поэтому он концептуально выполняется один раз для каждой строки во внешнем запросе (без оптимизации базы данных). Что он делает, так это подсчитывает, сколько сотрудников имеют зарплату больше, чем у одного в строке во внешнем запросе: если есть 2 сотрудника с более высокой зарплатой, то вы знаете, что сотрудник в текущей строке во внешнем запросе имеет третью по величине зарплату.

Другой способ сформулировать это использовать row_number() для этого:

select *
from (
    select 
        e.*, 
        row_number() over(order by salary desc) rn 
    from employee e
) t
where rn = 3

В зависимости от того, как вы хотите обрабатывать дубликаты, dense_rank() также может быть вариантом.

0 голосов
/ 20 февраля 2020

Проще понять, когда вы запустите этот запрос:

select e1.*, 
       (select count(distinct e2.salary)
          from employee e2
          where e2.salary > e1.salary) as n
  from employee e1

Это моя примерная таблица:

create table employee(salary) as (
  select * from table(sys.odcinumberlist(1500, 1200, 1400, 1500, 1100)));

, поэтому мой вывод:

    SALARY          N
---------- ----------
      1500          0
      1200          2
      1400          1
      1500          0
      1100          3

Как видно, подзапрос подсчитывает для каждой строки зарплаты, превышающие зарплату в текущей строке. Так, например, на 1400 год на ЗНАЧИТЕЛЬНО большую зарплату (1500). 1500 появляется в моей таблице дважды, но distinct означает, что он считается один раз. Таким образом, 1400 - второй по порядку.

В вашем запросе этот счет перемещен в часть where и сравнен с требуемым значением. Мы должны вычесть один, потому что для самой высокой зарплаты нет более высокого значения, для второй зарплаты одна строка et c.

Это один из методов, используемых для поиска таких значений, в более новых Oracle версиях введены аналитические c функции (rank, row_number, dens_rank), что исключает необходимость использования подзапросов для таких целей. Они быстрее, эффективнее. Для вашего запроса было бы полезно dense_rank().

0 голосов
/ 20 февраля 2020
SELECT * FROM (SELECT EMP.ID,RANK() OVER (ORDER BY SALARY DESC) AS NOS FROM EMPLOYEE) T WHERE T.NOS=3

Тогда из этого выберите тот с любым желаемым рангом.

...