Để chọn hàng từ bảng A **chỉ khi tồn tại** hàng tương ứng trong bảng B (theo cột chung), dùng mệnh đề EXISTS với **subquery tương quan (correlated subquery)**. Cách này thường hiệu quả hơn IN hoặc JOIN khi chỉ cần kiểm tra sự tồn tại.
Cú pháp
SELECT cot_a FROM bang_a a
WHERE EXISTS (
SELECT 1 FROM bang_b b
WHERE a.cot_khoa = b.cot_khoa
);
SELECT 1: chỉ kiểm tra tồn tại, không cần lấy dữ liệu thực.- Subquery tham chiếu
a.cot_khoatừ bảng ngoài → correlated.
Ví dụ minh họa
Bảng 1: Môn học (có trùng 'MySQL'):
mysql> CREATE TABLE DemoTable1 (Id INT, SubjectName VARCHAR(20));
mysql> INSERT INTO DemoTable1 VALUES
-> (111,'MySQL'), (112,'MongoDB'), (113,'Java'), (114,'C'), (115,'MySQL');
Bảng 2: Sinh viên - Môn học:
mysql> CREATE TABLE DemoTable2 (FirstName VARCHAR(20), StudentSubject VARCHAR(20));
mysql> INSERT INTO DemoTable2 VALUES
-> ('Chris','MySQL'), ('Bob','MySQL'), ('Sam','MySQL'), ('Carol','C');
Truy vấn: Lấy Id từ DemoTable1 **chỉ khi SubjectName xuất hiện trong DemoTable2**:
mysql> SELECT Id FROM DemoTable1
-> WHERE EXISTS (
-> SELECT 1 FROM DemoTable2
-> WHERE SubjectName = StudentSubject
-> );
Kết quả (Id 111, 114, 115 – môn MySQL và C có trong bảng 2):
+------+ | Id | +------+ | 111 | | 114 | | 115 | +------+
So sánh EXISTS vs IN vs JOIN
| Phép | Đặc điểm | Phù hợp khi |
|---|---|---|
| EXISTS | Dừng sớm khi tìm thấy 1 khớp; không nhân bản hàng | Chỉ cần kiểm tra tồn tại; bảng ngoài lớn, bảng trong nhỏ |
| IN (subquery) | Tương tự EXISTS; MySQL tối ưu hóa gần như giống nhau | Danh sách giá trị nhỏ, tĩnh |
| INNER JOIN | Nhân bản hàng nếu khớp nhiều lần; cần DISTINCT | Cần cột từ cả 2 bảng; hoặc muốn lọc trùng |
Mẹo hiệu năng
- Tạo index trên cột join (
SubjectName,StudentSubject). - Với MySQL 8.0+, optimizer chuyển đổi EXISTS ↔ IN ↔ SEMI-JOIN tự động.