#sql #oracle
#sql #Oracle
Вопрос:
Мне нужно создать запрос, который показывает фамилию сотрудника, идентификатор сотрудника, фамилию менеджера этого сотрудника и идентификатор этого менеджера.
Легко ввести фамилию, идентификатор и идентификатор менеджера этого сотрудника, поскольку они уже находятся в одной строке, что означает, что достаточно следующего:
SELECT last_name, employee_id, manager_id FROM employees WHERE manager_id IS NOT NULL;
Но чтобы получить last_name менеджера, вам нужно выполнить поиск в той же таблице по идентификатору менеджера, который вы получили от сотрудника. Решение, которое я нашел, это:
SELECT last_name,
employee_id,
(SELECT last_name FROM employees WHERE employee_id = manager_id),
manager_id
FROM employees
WHERE manager_id IS NOT NULL;
Однако, похоже, что ‘manager_id’ не работает в подзапросе (хотя я ожидал этого), и вывод имеет значение NULL (для идентификатора менеджера все остальные столбцы имеют значения).
Итак, мой вопрос в том, как я могу использовать manager_id в подзапросе?
Примечание: идентификатор manager_id может отличаться для каждого сотрудника, поэтому использование постоянного значения не работает.
Ответ №1:
Что вам нужно, так это коррелированный подзапрос. Я настоятельно, настоятельно рекомендую вам использовать псевдонимы таблиц и полные имена столбцов во всех ваших запросах. Однако это особенно важно для коррелированных подзапросов.
Вы должны написать этот запрос как:
SELECT e.last_name, e.employee_id,
(SELECT m.last_name
FROM employees m
WHERE m.employee_id = e.manager_id
),
e.manager_id
FROM employees e
WHERE e.manager_id IS NOT NULL;
Псевдоним e
— это сокращение для ссылки на таблицу employees
во внешнем запросе. Псевдоним m
— это сокращение для ссылки на таблицу в подзапросе.
Обратите внимание, что все ссылки на столбцы используют псевдоним таблицы. Это делает запрос однозначным, может предотвратить непредвиденные ошибки и значительно упрощает понимание запроса для вас и других пользователей.
Комментарии:
1. 1 за то, что вы нашли время, чтобы объяснить в понятных выражениях, что вы здесь делаете и почему. Готовность помочь менее опытному сотруднику очень ценится.
Ответ №2:
Вы могли бы использовать собственное внутреннее соединение (соединение с той же таблицей)
SELECT
a.last_name
, a.employee_id
, b.last_name
, a.manager_id
FROM employees a
INNER JOIN employees b ON b.employee_id = a.manager_id;
Внутреннее соединение работает, только если.manager_id не равен null, поэтому вы можете избежать этого условия where
Комментарии:
1. Я смог заставить его работать, изменив запрос на:
SELECT a.last_name, a.employee_id, (SELECT b.last_name FROM employees WHERE b.employee_id = a.manager_id), a.manager_id FROM employees a INNER JOIN employees b ON b.employee_id = a.manager_id WHERE a.manager_id IS NOT NULL;
но запрос от Гордона Линоффа работал без изменений, поэтому я принимаю его ответ.2.
, b.last_name FROM employees WHERE employee_id = manager_id
это совершенно неправильно
Ответ №3:
Когда вы хотите сослаться на таблицу во внешнем запросе, вам нужно либо использовать полное имя таблицы, подобное table.field
, либо, как в вашем случае, если таблица внешнего запроса совпадает с таблицей подзапросов, вам нужно присвоить псевдоним таблице внешнего запроса и использовать его в подзапросе, подобном это:
SELECT
last_name, employee_id,
(SELECT last_name FROM employees WHERE employee_id = emp_outer.manager_id),
manager_id
FROM employees emp_outer
WHERE manager_id IS NOT NULL;
Комментарии:
1. Это в основном правильное и «минимальное» решение (хотя совет Гордона использовать псевдоним таблицы для копии таблицы подзапроса действительно очень хороший совет, даже если он не является строго обязательным). Требуется псевдоним для внешнего запроса, и это то, что вы показываете здесь. Однако есть два момента: в Oracle вы не можете использовать ключевое слово «AS» перед псевдонимом таблицы (это вызовет синтаксическую ошибку); вы можете только (НЕОБЯЗАТЕЛЬНО!) Использовать слово «AS» перед псевдонимом столбца. И, как правило, лучше всего использовать (очень) короткие псевдонимы для таблиц. «emp_outer» технически корректен, но при его частом использовании потребуется много ввода.
2. @mathguy Я предоставил минимальное решение и длинный псевдоним, чтобы оператору было ясно, как обращаться к внешней таблице. Хороший момент для ключевого слова ‘as’, я не знал, что oracle не разрешает это, поскольку я не часто использую Oracle.. Спасибо