Giới thiệu MySQL CTE
Bài viết này hướng dẫn cách sử dụng MySQL common table expression (MySQL CTE) để xây dựng các queries phức tạp theo một cách dễ đọc hơn.
Tính năng common table expression (CTE) được sử dụng từ version 8.0. Vì vậy các bạn nên cài đặt MySQL 8.0 để thực hiện theo bài viết này
Common table expression (CTE) là gì?
Một common table expression hay CTE là kết quả tạm thời được đặt tên và chỉ tồn tại trong phạm vi thực thi một câu lệnh như: SELECT, INSERT, UPDATE hoặc DELETE.
Giống như với Derived Table, CTE không được lưu như 1 object mà chỉ tồn tại trong suốt quá trình thực thi truy vấn.
Khác với Derived Table, CTE có thể tự tham chiếu (CTE đệ qui) hoặc có thể được tham chiếu nhiều lần trong cùng 1 truy vấn. Ngoài ra, CTE cung cấp khả năng đọc và hiệu suất tốt hơn so với Derived Table.
Cú pháp MySQL CTE
Cấu trúc của CTE bao gồm:
- name
- danh sách optional column
- truy vấn xác định CTE
Sau khi CTE được định nghĩa, ta có thể sử dụng nó như 1 view trong các lệnh SELECT, INSERT, UPDATE, DELETE hoặc CREATE VIEW.
Basic syntax của CTE:
WITH cte_name (column_list) AS (
query
)
SELECT * FROM cte_name;
Lưu ý rằng, số lượng columns trong query phải bằng với số columns trong column_list. Nếu không sử dụng column_list, CTE sẽ sử dụng column list của query đã định nghĩa CTE.
Simple MySQL CTE examples
Ví dụ sau chỉ ra cách sử dụng CTE để truy vấn dữ liệu từ bảng customers, các bạn có thể download database sample tại đây.
Ví dụ 1:
WITH customers_in_usa AS (
SELECT
customerName, state
FROM
customers
WHERE
country = 'USA'
) SELECT
customerName, state
FROM
customers_in_usa
WHERE
state = 'CA'
ORDER BY customerName;

Trong ví dụ này, CTE là customers_in_usa, trong truy vấn CTE trả về 2 column customerName và state cùng với điều kiện là tất cả customers ở USA.
Sau khi CTE được định nghĩa, chúng ta sẽ tham chiếu nó vào câu lệnh SELECT để chỉ chọn các customers ở bang California mà thôi.
Ví dụ 2:
WITH topsales2003 AS (
SELECT
salesRepEmployeeNumber employeeNumber,
SUM(quantityOrdered * priceEach) sales
FROM
orders
INNER JOIN
orderdetails USING (orderNumber)
INNER JOIN
customers USING (customerNumber)
WHERE
YEAR(shippedDate) = 2003
AND status = 'Shipped'
GROUP BY salesRepEmployeeNumber
ORDER BY sales DESC
LIMIT 5
)
SELECT
employeeNumber, firstName, lastName, sales
FROM
employees
JOIN
topsales2003 USING (employeeNumber);

Trong ví dụ này, CTE topsales2003 sẽ trả về top 5 sales trong năm 2003. Sau đó, tham chiếu CTE để lấy thông tin về sales bao gồm cả first và last name.
Ví dụ 3:
WITH salesrep AS (
SELECT
employeeNumber,
CONCAT(firstName, ' ', lastName) AS salesrepName
FROM
employees
WHERE
jobTitle = 'Sales Rep'
),
customer_salesrep AS (
SELECT
customerName, salesrepName
FROM
customers
INNER JOIN
salesrep ON employeeNumber = salesrepEmployeeNumber
)
SELECT
*
FROM
customer_salesrep
ORDER BY customerName;

Ở ví dụ này, 2 CTEs đước sử dụng. CTE đầu tiên (salesrep) lấy các nhân viên với jobTitle là ‘Sales Rep’. CTE thứ 2 (customer_salesrep) tham chiếu tới CTE salesrep trong lệnh INNER JOIN để lấy sales rep và customers tương ứng của mỗi sales rep đứng ra chịu trách nhiệm.
Sau đó tham chiếu tới CTE thứ 2 để lấy dữ liệu có sử dụng lệnh ORDER BY
WITH clause usages
Một số trường hợp sử dụng WITH để tạo CTE:
1. WITH được sử dụng khi bắt đầu lệnh SELECT, UPDATE hoặc DELETE.
WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...
2. WITH được sử dụng khi bắt đầu subquery hoặc derived table subquery.
SELECT ... WHERE id IN (WITH ... SELECT ...);
SELECT * FROM (WITH ... SELECT ...) AS derived_table;
3. WITH được sử dụng ngay trước khi SELECT bao gồm cả lệnh SELECT.
CREATE TABLE ... WITH ... SELECT ...
CREATE VIEW ... WITH ... SELECT ...
INSERT ... WITH ... SELECT ...
REPLACE ... WITH ... SELECT ...
DECLARE CURSOR ... WITH ... SELECT ...
EXPLAIN ... WITH ... SELECT ...
Hi vọng bài viết này sẽ giúp các bạn hiểu rõ hơn về cách dùng MySQL CTE.
Hãy like, share & comment để cùng học nhé!