Về Subquery – Truy Vấn Con Trong SQL

4 min read

Trong thế giới quản trị cơ sở dữ liệu, SQL (Structured Query Language) là ngôn ngữ chủ đạo để tương tác với dữ liệu. Một trong những khái niệm quan trọng và mạnh mẽ trong SQL chính là subquery (truy vấn phụ).

Subquery Là Gì?

Đơn giản thôi, subquery là một truy vấn con, được đặt bên trong một truy vấn khác. Cách làm này cho phép chúng ta “chia nhỏ” vấn đề phức tạp thành các truy vấn đơn giản hơn. Kết quả của subquery sẽ được dùng bởi truy vấn lớn bên ngoài để tạo ra kết quả cuối cùng.

Một ví dụ dễ hiểu:

Giả sử chúng ta có hai bảng: bảng Employees (Nhân viên) và bảng Departments (Phòng ban). Bảng Employees lưu thông tin về nhân viên và lương của họ, còn bảng Departments lưu tên các phòng ban.

Nhiệm vụ là: tìm các nhân viên có lương cao hơn mức trung bình của phòng ban họ.

Câu truy vấn sẽ trông như thế này:

SELECT Name, Salary
FROM Employees e
WHERE Salary > (
SELECT AVG(Salary)
FROM Employees
WHERE DepartmentID = e.DepartmentID
);

Ở đây, subquery của chúng ta (phần nằm trong dấu ngoặc) sẽ tính lương trung bình cho từng phòng ban. Sau đó, truy vấn chính sẽ lấy tên và lương của những nhân viên có mức lương cao hơn con số trung bình mà subquery tính được.

Các Loại Subquery

Subquery có hai dạng phổ biến: Không liên kếtLiên kết.

1. Subquery Không Liên Kết (Non-Correlated Subquery)

Đây là dạng dễ hiểu nhất. Subquery không liên quan gì đến truy vấn chính, nó được thực thi một lần duy nhất và kết quả được dùng trong truy vấn chính.

Ví dụ, nếu mình muốn tìm những nhân viên có lương cao hơn mức trung bình của toàn bộ công ty:

SELECT Name, Salary
FROM Employees
WHERE Salary > (SELECT AVG(Salary) FROM Employees);

Ở đây, subquery chỉ tính lương trung bình của toàn bộ nhân viên một lần, sau đó kết quả được sử dụng cho tất cả các dòng trong bảng Employees.

2. Subquery Liên Kết (Correlated Subquery)

Dạng này thì thú vị hơn vì nó liên quan trực tiếp đến từng dòng của truy vấn chính. Subquery sẽ được thực thi lại mỗi khi truy vấn chính xử lý một dòng mới.

Ví dụ lại với bài toán nhân viên có lương cao hơn mức trung bình của phòng ban:

SELECT Name, Salary
FROM Employees e
WHERE Salary > (
SELECT AVG(Salary)
FROM Employees
WHERE DepartmentID = e.DepartmentID
);

Ở đây, mỗi lần truy vấn chính xử lý một nhân viên trong bảng Employees, subquery sẽ chạy để tính lương trung bình của phòng ban mà nhân viên đó làm việc.

Khi Nào Nên Dùng Subquery, Khi Nào Dùng JOIN?

Một câu hỏi phổ biến là: Nên dùng subquery hay JOIN?

Thực ra cả hai đều có thể giúp bạn kết hợp dữ liệu từ nhiều bảng, nhưng mỗi cách có ưu điểm riêng:

  • Subquery: Dễ hiểu hơn khi bạn chỉ muốn lấy dữ liệu theo một điều kiện cụ thể. Nhưng đôi khi, nếu subquery quá phức tạp hoặc liên quan đến nhiều dữ liệu, nó có thể chậm hơn.
  • JOIN: Nhanh hơn trong nhiều trường hợp khi bạn cần kết hợp dữ liệu từ nhiều bảng mà không phải lồng truy vấn.

Ví dụ, bạn có thể viết lại bài toán trên bằng JOIN như sau:

SELECT e.Name, e.Salary
FROM Employees e
JOIN (
SELECT DepartmentID, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY DepartmentID
) d ON e.DepartmentID = d.DepartmentID
WHERE e.Salary > d.AvgSalary;

Cả hai cách đều đúng, chỉ là tùy tình huống mà chúng ta chọn cách nào tối ưu hơn.

Một Số Ứng Dụng Của Subquery Trong Thực Tế

Dưới đây là một số ví dụ thực tế mình hay gặp phải khi làm việc với subquery:

  1. Lọc dữ liệu dựa trên điều kiện phức tạp: Nếu chỉ cần lọc ra những dòng thoả mãn một điều kiện phụ, subquery là lựa chọn tuyệt vời.
  2. Kiểm tra sự tồn tại: Dùng EXISTS hoặc IN với subquery để kiểm tra xem dữ liệu có tồn tại trong bảng khác hay không.
  3. Tính toán các giá trị tổng hợp: Ví dụ tính trung bình, tổng hoặc số lượng trong một tập hợp dữ liệu con.

Ví dụ: Tìm tất cả các phòng ban có ít hơn 3 nhân viên:

SELECT DepartmentName
FROM Departments d
WHERE (
SELECT COUNT(*)
FROM Employees e
WHERE e.DepartmentID = d.DepartmentID
) < 3;

Subquery ở đây sẽ đếm số lượng nhân viên trong từng phòng ban, và truy vấn chính sẽ lọc ra những phòng ban nào có ít hơn 3 nhân viên.

Kết Luận

Subquery không phải là khái niệm phức tạp nếu bạn hiểu rõ bản chất của nó. Chỉ cần nhớ rằng, subquery là một cách để chia nhỏ các bài toán phức tạp, giúp bạn truy xuất dữ liệu theo cách linh hoạt hơn. Tuy nhiên, bạn cũng nên xem xét hiệu suất khi làm việc với lượng dữ liệu lớn và cân nhắc sử dụng JOIN khi cần thiết.

Tham khảo: https://dev.to/pwn0x80/subquery-vs-correlated-query-1622

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *