SELECT `table_1`.*
FROM `table_1`
INNER JOIN
`table_2` [...]
INNER JOIN
`table_3` [...]
WHERE `table_1`.`id` IN
(
SELECT `id`
FROM [...]
)
AND [more conditions]
Nếu bảng bên trong được lập chỉ mục đúng cách, truy vấn con ở đây hoàn toàn không được "thực hiện" theo nghĩa chặt chẽ của từ này.
Vì truy vấn con là một phần của IN
biểu thức, điều kiện được đẩy vào truy vấn con và nó được chuyển thành EXISTS
.
Trên thực tế, truy vấn con này được đánh giá theo từng bước:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Bạn thực sự có thể thấy nó trong mô tả chi tiết được cung cấp bởi EXPLAIN EXTENDED
.
Đó là lý do tại sao nó được gọi là DEPENDENT SUBQUERY
:kết quả của mỗi lần đánh giá phụ thuộc vào giá trị của table1.id
. Truy vấn con như vậy không có tương quan, đó là phiên bản được tối ưu hóa có tương quan.
MySQL
luôn đánh giá EXISTS
mệnh đề sau các bộ lọc đơn giản hơn (vì chúng dễ đánh giá hơn nhiều và có khả năng truy vấn con hoàn toàn không được đánh giá).
Nếu bạn muốn toàn bộ truy vấn con được đánh giá cùng một lúc, hãy viết lại truy vấn như sau:
SELECT table_1.*
FROM (
SELECT DISTINCT id
FROM [...]
) q
JOIN table_1
ON table_1.id = q.id
JOIN table_2
ON [...]
JOIN table_3
ON [...]
WHERE [more conditions]
Điều này buộc truy vấn con phải đứng đầu trong phép nối, điều này sẽ hiệu quả hơn nếu truy vấn con nhỏ so với table_1
và kém hiệu quả hơn nếu truy vấn con lớn so với table_1
.
Nếu có chỉ mục trên [...].id
được sử dụng trong truy vấn con, truy vấn con sẽ được thực hiện bằng cách sử dụng INDEX FOR GROUP-BY
.