Це дуже гарне запитання, тому я вирішив написати дуже докладну статтю на цю тему у своєму блозі.
Модель таблиці бази даних
Припустимо, що в нашій базі даних є наступні дві таблиці, які утворюють взаємозв'язок таблиці "один до багатьох".
student
Таблиця є батьком, і student_grade
є дочірньою таблицею , так як він має student_id стовпець зовнішнього ключа , який посилається Ід стовпець первинного ключа в таблиці студента.
student table
Містить наступні два записи:
| id | first_name | last_name | admission_score |
|
| 1 | Alice | Smith | 8.95 |
| 2 | Bob | Johnson | 8.75 |
І в student_grade
таблиці зберігаються оцінки, отримані студентами:
| id | class_name | grade | student_id |
|
| 1 | Math | 10 | 1 |
| 2 | Math | 9.5 | 1 |
| 3 | Math | 9.75 | 1 |
| 4 | Science | 9.5 | 1 |
| 5 | Science | 9 | 1 |
| 6 | Science | 9.25 | 1 |
| 7 | Math | 8.5 | 2 |
| 8 | Math | 9.5 | 2 |
| 9 | Math | 9 | 2 |
| 10 | Science | 10 | 2 |
| 11 | Science | 9.4 | 2 |
SQL ІСНУЄ
Скажімо, ми хочемо отримати всіх учнів, які отримали 10 оцінок на уроці математики.
Якщо нас цікавить лише ідентифікатор студента, ми можемо виконати такий запит:
SELECT
student_grade.student_id
FROM
student_grade
WHERE
student_grade.grade = 10 AND
student_grade.class_name = 'Math'
ORDER BY
student_grade.student_id
Але додаток зацікавлений у відображенні повного імені student
, а не лише ідентифікатора, тому нам також потрібна інформація з student
таблиці.
Для того, щоб відфільтрувати student
записи, які мають математичну оцінку 10, ми можемо використовувати оператор SQL ІСНУЄ, наприклад:
SELECT
id, first_name, last_name
FROM
student
WHERE EXISTS (
SELECT 1
FROM
student_grade
WHERE
student_grade.student_id = student.id AND
student_grade.grade = 10 AND
student_grade.class_name = 'Math'
)
ORDER BY id
При запуску запиту вище ми бачимо, що вибрано лише рядок Аліса:
| id | first_name | last_name |
|
| 1 | Alice | Smith |
Зовнішній запит вибирає student
стовпці рядків, які ми хочемо повернути клієнту. Однак речення WHERE використовує оператор EXISTS із пов'язаним внутрішнім підзапитом.
Оператор EXISTS повертає true, якщо підзапит повертає принаймні один запис, і false, якщо не вибрано жодного рядка. Механізм бази даних не повинен повністю запускати підзапит. Якщо збігається один запис, оператор EXISTS повертає true, і вибирається пов'язаний інший рядок запиту.
Внутрішній підзапит корелює, оскільки стовпець student_id student_grade
таблиці відповідає стовпцю id зовнішньої таблиці студента.