2016-11-08 2 views
-1

У меня есть таблица сотрудников из схемы HR (оракул). Это, как я выполнил задачу (выбрать сотрудников с минимальной заработной платы в своих подразделениях, если они принадлежат к какой-либо из них)Есть ли способ переписать этот запрос без подзапросов?

SELECT D.employee_id,D.Last_name,D.salary,D.department_id 
    FROM [HelpDatabase].[dbo].[Employees] D, 
     [HelpDatabase].[dbo].[Employees] E 
    WHERE D.department_id IS NOT NULL 
     AND E.department_id IS NOT NULL 
     AND D.employee_id=E.employee_id 
     AND D.salary=ANY (
      SELECT MIN(E.salary) 
      FROM [HelpDatabase].[dbo].[Employees] 
      GROUP BY E.department_id) 

запрос работает правильно, но мне сказали, что есть способ сделать это без использования подзапрос.

+0

bs - этот запрос не может работать корректно, поскольку он имеет синтаксические ошибки. – mathguy

+0

@mathguy - только в плохо обфусканных именах таблиц ... (это почти стандартные таблицы сотрудников и отделов, но почему у отделов будет столбец employee_id, это немного загадка) –

+0

@mathguy вы правы, отредактировал его. – Shady119

ответ

1

Предположим, вы просто хотите найти сотрудников, которые получают самые низкие зарплаты в своих отделах:

Да, это можно сделать без подзапроса. Идея заключается в том, что вы можете искать сотрудников, для которых не существует другого сотрудника в том же отделе и более низкую зарплату:

select * 
from emp 
where not exists 
(
    select * 
    from emp less 
    where less.department_id = emp.department_id and less.salary < emp.salary 
); 

NOT EXISTS запрос также может быть записана в виде анти-соединения. Это: внешнее соединение с менее трудолюбивыми сотрудниками; затем удалите из результатов всех сотрудников, где вы нашли таких лиц.

select * 
from emp 
left join emp less on less.department_id = emp.department_id and less.salary < emp.salary 
where less.employee_id is null; 

Вы обычно не сделать это, хотя, потому что это уловка, и это немного запутанным, что запрос фактически делает. NOT EXISTS здесь яснее, спрашивая «дайте мне сотрудников, для которых не существует коллег, которые зарабатывают меньше».

(Ну, в вашем случае вы можете даже использовать что-то совсем другое, например, where (department_id, salary) in (select department_id, min(salary) ...) или rank() over partition by department_id order by salary.)

Но анти соединениями является решением, когда ваша СУБД оказывается слабой на not exists запросов. Это просто другой способ написать одно и то же.

-1
SELECT D.employee_id,D.Last_name,MIN(D.salary),D.department_id 
    FROM [HelpDatabase].[dbo].[Employees] D 
    WHERE D.department_id IS NOT NULL 
    group by D.employee_id,D.Last_name,D.department_id 
+0

Это не работает правильно, однако я не уверен, почему. – Shady119

+0

Группировка employee_id приведет к одному сотруднику в каждой группе –

0
SELECT D.employee_id,D.Last_name,D.salary,D.department_id 
FROM [HelpDatabase].[dbo].[Employees] D, 
    (SELECT department_id, MIN(salary) min_salary 
     FROM [HelpDatabase].[dbo].[Employees] 
     WHERE department_id is not null 
     GROUP BY department_id) E 
WHERE D.department_id IS NOT NULL 
    AND D.salary=E.min_salary 
    AND E.department_id=D.department_id 

Вы можете использовать мин (зарплаты) в течение (раздел по DEPARTMENT_ID) min_salary получить min_salary, но он все равно будет производить подзапросов и вам придется фильтровать строки после этого

+0

Отсутствует 'E.department_id = D.department_id'. Также используется подзапрос. – Taemyr

+0

Я добавил отличный от него, чтобы нормально работать. Кажется правильным, а не как мой в примере, но это еще два выбора, а не один. – Shady119

+0

пропущенный идентификатор department_id, обновленный ответ –

Смежные вопросы