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

У наведеному вище вкладеному запиті внутрішній запит повинен виконуватися повторно для кожного працівника (досить розумна реалізація може результат внутрішнього запиту на основі відділ-по-відділу, але навіть у найкращому випадку внутрішній запит повинен виконуватися один раз для кожного відділу).

Корельовані підзапити можуть з'являтися не тільки в операторі 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;

Посилання