Корельований підзапит
У запитах до баз даних SQL, корельований підзапит (також відомий як синхронізований підзапит) — це підзапит (запит, вкладений усередині іншого запиту), який використовує значення з зовнішнього запиту. Оскільки підзапит може бути обчислено один раз для кожного рядка, обробленого зовнішнім запитом, він може бути неефективним.
Нижче наведено приклад типового корельованого підзапиту. Метою даного прикладу є знайти всіх співробітників, заробітна платня яких вища за середню в їхньому відділі.
SELECT employee_number, name
FROM employees AS emp
WHERE salary > (SELECT AVG(salary)
FROM employees
WHERE department = emp.department);
У наведеному вище прикладі зовнішнім запитом є
SELECT employee_number, name
FROM employees AS emp
WHERE salary > ...
а внутрішнім запитом (корельованим підзапитом) є
SELECT AVG(salary)
FROM employees
WHERE department = emp.department
У наведеному вище вкладеному запиті внутрішній запит повинен виконуватися повторно для кожного працівника (досить розумна реалізація може кешувати[en] результат внутрішнього запиту на основі відділ-по-відділу, але навіть у найкращому випадку внутрішній запит повинен виконуватися один раз для кожного відділу).
Корельовані підзапити можуть з'являтися не тільки в операторі WHERE; наприклад, такий запит використовує корельований підзапит в операторі SELECT, щоб надрукувати весь список співробітників разом із середньою заробітною платнею для кожного відділу. Знову ж таки, оскільки підзапит корелюється з колонкою зовнішнього запиту, він повинен повторно виконатися для кожного рядка результату.
SELECT employee_number,
name,
(SELECT AVG(salary)
FROM employees
WHERE department = emp.department) AS department_average
FROM employees AS emp;
Ефекту корельованих підзапитів у деяких випадках можна досягти, використовуючи з'єднання. Наприклад, вищенаведені запити (які використовують неефективні корельовані підзапити) можна переписати таким чином:
-- Цей підзапит не корелює з зовнішнім запитом, а тому виконується
-- тільки один раз незалежно від кількості співробітників.
SELECT employees.employee_number, employees.name
FROM employees
INNER JOIN (SELECT department, AVG(salary) AS department_average
FROM employees
GROUP BY department) AS temp
ON employees.department = temp.department
WHERE employees.salary > temp.department_average;
Якщо внутрішній запит використовується в декількох запитах, то він може бути збережений як розріз, після чого з'єднаний з іншими запитами:
CREATE VIEW dept_avg AS
SELECT department, AVG(salary) AS department_average
FROM employees
GROUP BY department;
-- List employees making more than their department average.
SELECT employees.employee_number, employees.name
FROM employees INNER JOIN dept_avg ON employees.department = dept_avg.department
WHERE employees.salary > dept_avg.department_average;
-- List employees alongside their respective department averages.
SELECT employees.employee_number, employees.name, dept_avg.department_average
GROUP BY department AS temp ON employee.department = temp.department
FROM employees INNER JOIN dept_avg ON employees.department = dept_avg.department;
DROP VIEW dept_avg;
- SQL Correlated Subquery. ZenTut (англійською) . Архів оригіналу за 19 травня 2017. Процитовано 3 червня 2017.
На цю статтю не посилаються інші статті Вікіпедії. Будь ласка розставте посилання відповідно до прийнятих рекомендацій. |