Bài 7: Sử dụng Subquery và CTE
Subquery và Common Table Expressions (CTE) là hai công cụ mạnh mẽ trong SQL, cho phép bạn chia nhỏ các truy vấn phức tạp thành các phần đơn giản hơn, dễ quản lý và tối ưu hóa. Bài viết này sẽ đi sâu vào khái niệm, cách sử dụng, và so sánh giữa subquery và CTE, đồng thời đưa ra các ví dụ cụ thể để minh họa.
7.1. Subquery là gì?
Subquery (truy vấn con) là một truy vấn SQL được lồng bên trong một truy vấn khác. Subquery có thể được sử dụng trong các mệnh đề SELECT
, FROM
, WHERE
, và HAVING
.
7.1.1. Cách sử dụng subquery
Trong mệnh đề WHERE: Subquery thường được sử dụng để lọc dữ liệu dựa trên kết quả của một truy vấn khác.
Ví dụ:
SELECT employee_id, first_name, last_name FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Sales');
Trong mệnh đề FROM: Subquery có thể được sử dụng như một bảng tạm thời trong truy vấn chính.
Ví dụ:
SELECT e.employee_id, e.first_name, d.department_name FROM employees e JOIN (SELECT department_id, department_name FROM departments WHERE location_id = 1) d ON e.department_id = d.department_id;
Trong mệnh đề SELECT: Subquery có thể được sử dụng để tính toán các giá trị động.
Ví dụ:
SELECT employee_id, first_name, last_name, (SELECT COUNT(*) FROM orders WHERE orders.employee_id = employees.employee_id) AS order_count FROM employees;
7.1.2. Ưu và nhược điểm của subquery
Ưu điểm:
Linh hoạt: Subquery có thể được sử dụng trong nhiều mệnh đề khác nhau.
Dễ hiểu: Subquery giúp chia nhỏ các truy vấn phức tạp thành các phần đơn giản hơn.
Nhược điểm:
Hiệu suất: Subquery có thể làm chậm truy vấn nếu không được tối ưu hóa, đặc biệt là khi sử dụng trong mệnh đề
SELECT
.Khó bảo trì: Các subquery lồng nhau có thể làm cho truy vấn trở nên khó đọc và khó bảo trì.
7.2. Common Table Expressions (CTE)
CTE là một biểu thức bảng tạm thời được định nghĩa trong phạm vi của một truy vấn SQL. CTE giúp làm cho truy vấn dễ đọc và dễ bảo trì hơn so với subquery.
7.2.1. Cú pháp và cách sử dụng CTE
Cú pháp:
WITH CTE_Name AS ( SELECT column1, column2 FROM table_name WHERE condition ) SELECT * FROM CTE_Name;
Ví dụ:
WITH SalesDept AS ( SELECT employee_id, first_name, last_name FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Sales') ) SELECT * FROM SalesDept;
7.2.2. So sánh CTE với subquery
Ưu điểm của CTE:
Dễ đọc: CTE giúp chia nhỏ truy vấn phức tạp thành các phần đơn giản hơn, dễ đọc và dễ bảo trì.
Tái sử dụng: CTE có thể được tham chiếu nhiều lần trong cùng một truy vấn, trong khi subquery phải được viết lại nhiều lần.
Nhược điểm của CTE:
- Hiệu suất: CTE có thể không hiệu quả bằng subquery trong một số trường hợp, đặc biệt là khi sử dụng với lượng dữ liệu lớn.
7.3. Khi nào nên sử dụng subquery hoặc CTE
7.3.1. Trường hợp phù hợp cho subquery
Khi cần lọc dữ liệu trong mệnh đề WHERE: Subquery là lựa chọn tốt khi bạn cần lọc dữ liệu dựa trên kết quả của một truy vấn khác.
Ví dụ:
SELECT employee_id, first_name, last_name FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Sales');
Khi cần tính toán giá trị động trong mệnh đề SELECT: Subquery có thể được sử dụng để tính toán các giá trị động mà không cần tạo thêm bảng tạm.
Ví dụ:
SELECT employee_id, first_name, last_name, (SELECT COUNT(*) FROM orders WHERE orders.employee_id = employees.employee_id) AS order_count FROM employees;
7.3.2. Trường hợp phù hợp cho CTE
Khi cần chia nhỏ truy vấn phức tạp: CTE là lựa chọn tốt khi bạn cần chia nhỏ một truy vấn phức tạp thành các phần đơn giản hơn, dễ quản lý.
Ví dụ:
WITH SalesDept AS ( SELECT employee_id, first_name, last_name FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Sales') ), HighEarners AS ( SELECT employee_id, first_name, last_name FROM SalesDept WHERE salary > 50000 ) SELECT * FROM HighEarners;
Khi cần tái sử dụng kết quả truy vấn: CTE có thể được tham chiếu nhiều lần trong cùng một truy vấn, giúp tránh việc viết lại subquery nhiều lần.
Ví dụ:
WITH DeptEmployeeCount AS ( SELECT department_id, COUNT(*) AS employee_count FROM employees GROUP BY department_id ) SELECT d.department_name, dec.employee_count FROM departments d JOIN DeptEmployeeCount dec ON d.department_id = dec.department_id;
Kết luận
Subquery và CTE là hai công cụ mạnh mẽ giúp bạn chia nhỏ và tối ưu hóa các truy vấn phức tạp. Subquery phù hợp cho các tình huống cần lọc dữ liệu hoặc tính toán giá trị động, trong khi CTE là lựa chọn tốt khi bạn cần chia nhỏ truy vấn phức tạp và tái sử dụng kết quả truy vấn. Bằng cách hiểu rõ và sử dụng đúng cách cả hai công cụ này, bạn có thể cải thiện đáng kể hiệu suất và khả năng bảo trì của các truy vấn SQL.
Từ vựng chuyên môn (Glossary)
Subquery: Truy vấn con.
CTE (Common Table Expressions): Biểu thức bảng chung.
WHERE: Điều kiện lọc dữ liệu.
FROM: Mệnh đề chỉ định bảng dữ liệu.
SELECT: Mệnh đề chọn dữ liệu.
JOIN: Phép kết hợp dữ liệu từ nhiều bảng.
GROUP BY: Nhóm dữ liệu theo một hoặc nhiều cột.
HAVING: Điều kiện lọc dữ liệu sau khi nhóm.