Một subquery (truy vấn con) là một truy vấn lồng bên trong một truy vấn khác — được dùng trong WHERE, FROM, SELECT, hoặc với EXISTS. Nó cho phép bạn dùng kết quả của một truy vấn bên trong một truy vấn khác, hỗ trợ lọc và tính toán phức tạp.
Một subquery (truy vấn con) là một truy vấn lồng bên trong một truy vấn khác — được dùng trong WHERE, FROM, SELECT, hoặc với EXISTS. Nó cho phép bạn dùng kết quả của một truy vấn bên trong một truy vấn khác, hỗ trợ lọc và tính toán phức tạp.
-- tìm các user đã đặt đơn hàng (id của họ nằm trong bảng orders)
SELECT name FROM users
WHERE id IN (SELECT user_id FROM orders); -- subquery trả về một danh sách user_id
-- tìm các sản phẩm đắt hơn mức trung bình
SELECT name, price FROM products
WHERE price > (SELECT AVG(price) FROM products); -- subquery trả về một giá trị duy nhất
Một subquery trong WHERE cung cấp giá trị để lọc — một danh sách (với IN) hoặc một giá trị duy nhất (với toán tử so sánh).
-- với mỗi user, tìm những user có số đơn hàng trên trung bình CỦA QUỐC GIA HỌ
SELECT name FROM users u
WHERE order_count > (
SELECT AVG(order_count) FROM users
WHERE country = u.country -- tham chiếu dòng của truy vấn NGOÀI (tương quan)
);
Một subquery tương quan (correlated) tham chiếu truy vấn ngoài — nó chạy một lần cho mỗi dòng ngoài (có thể chậm hơn). Một subquery không tương quan chạy một lần.
-- các user có ít nhất một đơn hàng (thường hiệu quả hơn IN)
SELECT name FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id -- chỉ kiểm tra sự tồn tại
);
EXISTS kiểm tra xem một subquery có trả về bất kỳ dòng nào không — thường hiệu quả hơn IN cho việc kiểm tra tồn tại (nó có thể dừng ở match đầu tiên).
-- dùng kết quả subquery như một bảng
SELECT country, avg_age FROM (
SELECT country, AVG(age) AS avg_age FROM users GROUP BY country
) AS country_stats
WHERE avg_age > 30;
Nhiều subquery có thể được viết lại thành JOIN (thường hiệu quả/dễ đọc hơn).
WHERE id IN (SELECT ...) → thường có thể là một JOIN
Dùng subquery để rõ ràng trong lọc/tổng hợp; JOIN để kết hợp dữ liệu.
CTE (WITH) thường là lựa chọn sạch hơn cho các subquery lồng nhau phức tạp.
Subquery là một kỹ thuật SQL quan trọng cho truy vấn phức tạp — dùng kết quả của một truy vấn bên trong một truy vấn khác cho phép lọc và tính toán mà các truy vấn đơn giản không diễn đạt được, nên hiểu chúng có giá trị để viết các truy vấn thực tế.
Biết các dạng — subquery trong WHERE (lọc theo danh sách với IN hoặc một giá trị duy nhất với toán tử so sánh), subquery tương quan (tham chiếu truy vấn ngoài, chạy theo từng dòng), EXISTS (kiểm tra tồn tại hiệu quả) và subquery trong FROM (bảng dẫn xuất) — bao quát các mẫu phổ biến để diễn đạt logic phức tạp.
Hiểu sự khác biệt giữa subquery tương quan và không tương quan là quan trọng cho hiệu năng (subquery tương quan chạy một lần cho mỗi dòng ngoài và có thể chậm).
Cũng giá trị không kém là biết mối quan hệ với JOIN và CTE: nhiều subquery có thể viết lại thành JOIN (thường hiệu quả và dễ đọc hơn) hoặc CTE (sạch hơn cho các trường hợp phức tạp), nên hiểu khi nào dùng cái nào — subquery để lọc/tổng hợp rõ ràng, JOIN để kết hợp dữ liệu — là một kỹ năng thực tế.
Vì các truy vấn thực tế thường cần lồng nhau (lọc theo kết quả đã tổng hợp, kiểm tra tồn tại, so sánh với giá trị được tính), và vì hiểu subquery, đặc tính hiệu năng của chúng (đặc biệt loại tương quan) và mối quan hệ với JOIN/CTE là quan trọng để viết các truy vấn phức tạp hiệu quả, thành thạo subquery là kiến thức giá trị, được áp dụng thường xuyên cho SQL vượt qua truy vấn cơ bản và là một chủ đề phỏng vấn phổ biến cho thấy khả năng diễn đạt các yêu cầu dữ liệu phức tạp.