Как мне использовать значение из суперазапроса внутри подзапроса?

#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.. Спасибо