Корельований підзапит

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

У запитах до баз даних 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.