Đây là một câu hỏi rất hay, vì vậy tôi quyết định viết một bài viết rất chi tiết về chủ đề này trên blog của mình.
Mô hình bảng cơ sở dữ liệu
Giả sử chúng ta có hai bảng sau trong cơ sở dữ liệu của mình, tạo thành mối quan hệ một-nhiều bảng.
Các student
bảng là phụ huynh, vàstudent_grade
là bảng con vì nó có một cột nước ngoài chính student_id tham khảo id cột khóa chính trong bảng học sinh.
Các student table
chứa hai bản ghi sau:
| id | first_name | last_name | admission_score |
|----|------------|-----------|-----------------|
| 1 | Alice | Smith | 8.95 |
| 2 | Bob | Johnson | 8.75 |
Và student_grade
bảng lưu trữ các lớp học sinh nhận được:
| 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 |
EXISTS SQL
Giả sử chúng tôi muốn có được tất cả các học sinh đã nhận được một lớp 10 trong lớp Toán.
Nếu chúng ta chỉ quan tâm đến định danh sinh viên, thì chúng ta có thể chạy một truy vấn như thế này:
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
Nhưng, ứng dụng quan tâm đến việc hiển thị tên đầy đủ của a student
, không chỉ là mã định danh, vì vậy chúng tôi cũng cần thông tin từ student
bảng.
Để lọc các student
bản ghi có điểm 10 môn Toán, chúng ta có thể sử dụng toán tử EXISTS SQL, như sau:
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
Khi chạy truy vấn trên, chúng ta có thể thấy rằng chỉ có hàng Alice được chọn:
| id | first_name | last_name |
|----|------------|-----------|
| 1 | Alice | Smith |
Truy vấn bên ngoài chọn các student
cột hàng chúng tôi quan tâm để trả về máy khách. Tuy nhiên, mệnh đề WHERE đang sử dụng toán tử EXISTS với truy vấn con bên trong có liên quan.
Toán tử EXISTS trả về true nếu truy vấn con trả về ít nhất một bản ghi và false nếu không có hàng nào được chọn. Công cụ cơ sở dữ liệu không phải chạy hoàn toàn truy vấn con. Nếu một bản ghi được khớp, toán tử EXISTS trả về true và hàng truy vấn khác được liên kết được chọn.
Truy vấn con bên trong có tương quan vì cột student_id của student_grade
bảng được khớp với cột id của bảng sinh viên bên ngoài.
SQL KHÔNG EXIST
Hãy xem xét chúng tôi muốn chọn tất cả các học sinh không có điểm nào thấp hơn 9. Đối với điều này, chúng tôi có thể sử dụng KHÔNG EXISTS, điều này phủ nhận logic của toán tử EXISTS.
Do đó, toán tử NOT EXISTS trả về true nếu truy vấn con bên dưới không trả về bản ghi. Tuy nhiên, nếu một bản ghi được khớp với truy vấn con bên trong, toán tử NOT EXISTS sẽ trả về false và việc thực hiện truy vấn phụ có thể bị dừng.
Để khớp tất cả các hồ sơ học sinh không có student_THER liên quan với giá trị thấp hơn 9, chúng ta có thể chạy truy vấn SQL sau:
SELECT
id, first_name, last_name
FROM
student
WHERE NOT EXISTS (
SELECT 1
FROM
student_grade
WHERE
student_grade.student_id = student.id AND
student_grade.grade < 9
)
ORDER BY id
Khi chạy truy vấn trên, chúng ta có thể thấy rằng chỉ bản ghi Alice được khớp:
| id | first_name | last_name |
|----|------------|-----------|
| 1 | Alice | Smith |
Vì vậy, lợi thế của việc sử dụng các toán tử SQL EXISTS và KHÔNG EXISTS là việc thực thi truy vấn con bên trong có thể được dừng lại miễn là tìm thấy một bản ghi phù hợp.