Nếu như bạn đang hướng đến mục tiêu trở thành một DA – Data Analyst thì việc hiểu cũng như là sử dụng thành thạo lệnh with (Common Table Expression – CTE) vào trong những nhu cầu phân tích nâng cao là kỹ năng quan trọng, cần thiết. Vậy thì CTE trong SQL server là gì? Theo chân Comdy tìm hiểu chi tiết trong bài viết này nhé.
Giới thiệu về CTE trong SQL Server – CTE trong SQL là gì?

CTE SQL là gì?
CTE là gì? With CTE sql server là viết tắt của Common Table Expression (biểu thức bảng chung). Một CTE in sql server cho phép bạn định nghĩa một tập kết quả được đặt tên tạm thời mà có sẵn tạm thời trong phạm vi thực hiện một câu lệnh như SELECT
, INSERT
, UPDATE
, DELETE
hoặc MERGE
.
Sau đây là cú pháp chung của một CTE SQL Server:
WITH expression_name[(column_name [,...])]
AS
(CTE_definition)
SQL_statement;
Trong cú pháp này:
- Đầu tiên, chỉ định tên biểu thức (
expression_name
) mà bạn có thể tham chiếu đến sau này trong một truy vấn. - Tiếp theo, chỉ định danh sách các cột được phân tách bằng dấu phẩy sau
expression_name
. Số cột phải giống với số cột được xác định trongCTE_definition
. - Sau đó, sử dụng từ khóa AS sau tên biểu thức hoặc danh sách cột nếu danh sách cột được chỉ định.
- Sau đó, hãy định nghĩa một câu lệnh
SELECT
trả về tập kết quả điền cho CTE. - Cuối cùng, hãy sử dụng CTE trong sql server trong một truy vấn (
SQL_statement
) chẳng hạn nhưSELECT
,INSERT
,UPDATE
,DELETE
hoặcMERGE
.
Chúng tôi thích sử dụng CTE hơn là sử dụng các truy vấn con vì CTE dễ đọc hơn. Chúng tôi cũng sử dụng CTE trong các truy vấn có chứa analytic functions (hoặc window functions)
Ví dụ về CTE trong SQL Server

Một số ví dụ về việc sử dụng các biểu thức bảng phổ biến như sau:
Ví dụ CTE sql đơn giản
Truy vấn này sử dụng CTE để trả lại số tiền bán hàng của nhân viên kinh doanh trong năm 2018:
WITH cte_sales_amounts (staff, sales, year) AS (
SELECT
first_name + ' ' + last_name,
SUM(quantity * list_price * (1 - discount)),
YEAR(order_date)
FROM
sales.orders o
INNER JOIN sales.order_items i ON i.order_id = o.order_id
INNER JOIN sales.staffs s ON s.staff_id = o.staff_id
GROUP BY
first_name + ' ' + last_name,
year(order_date)
)
SELECT
staff,
sales
FROM
cte_sales_amounts
WHERE
year = 2018;
Trong ví dụ này:
- Đầu tiên, chúng ta định nghĩa
cte_sales_amounts
là tên của CTE. CTE trả về một tập kết quả gồm có ba cộtstaff
,year
vàsales
. - Thứ hai, chúng ta tạo một truy vấn trả về số lượng tổng doanh thu của nhân viên bán hàng và năm bằng cách truy vấn dữ liệu từ bảng
orders
,order_items
vàstaffs
. - Thứ ba, chúng ta sử dụng CTE trong truy vấn bên ngoài và chỉ chọn các bản ghi có năm là 2018.
Lưu ý rằng ví dụ này chỉ nhằm mục đích trình diễn để giúp bạn dần dần hiểu được cách thức hoạt động của các biểu thức bảng thông thường. Có một cách tối ưu hơn để đạt được kết quả mà không cần sử dụng CTE.
Sử dụng sql server CTE để tạo báo cáo trung bình dựa trên số lượng
Ví dụ này sử dụng CTE để trả về số lượng đơn hàng trung bình trong năm 2018 cho tất cả nhân viên bán hàng.
WITH cte_sales AS (
SELECT
staff_id,
COUNT(*) order_count
FROM
sales.orders
WHERE
YEAR(order_date) = 2018
GROUP BY
staff_id
)
SELECT
AVG(order_count) average_orders_by_staff
FROM
cte_sales;
Đây là đầu ra:
average_orders_by_staff
-----------------------
48
(1 row affected)
Trong ví dụ này:
Đầu tiên, chúng ta sử dụng cte_sales
làm tên của with CTE in SQL server. Chúng ta đã bỏ qua danh sách cột của CTE để nó được lấy từ câu lệnh định nghĩa CTE. Trong ví dụ này, nó bao gồm các cột staff_id
và order_count
.
Thứ hai, chúng ta sử dụng truy vấn sau để xác định tập kết quả của cte_sales
. Truy vấn trả về số lượng đơn hàng trong năm 2018 của nhân viên kinh doanh.
SELECT
staff_id,
COUNT(*) order_count
FROM
sales.orders
WHERE
YEAR(order_date) = 2018
GROUP BY
staff_id;
Thứ ba, chúng ta sử dụng cte_sales
trong câu lệnh bên ngoài và sử dụng hàm AVG()
để lấy số lượng đơn hàng trung bình của tất cả nhân viên.
SELECT
AVG(order_count) average_orders_by_staff
FROM
cte_sales;
Sử dụng nhiều CTE trong một truy vấn duy nhất
Ví dụ sau sử dụng 2 SQL server with CTE cte_category_counts
và cte_category_sales
để trả về số lượng sản phẩm và doanh số cho từng loại sản phẩm. Truy vấn bên ngoài sẽ join hai CTE bằng cách sử dụng cột category_id
.
WITH cte_category_counts (
category_id,
category_name,
product_count
)
AS (
SELECT
c.category_id,
c.category_name,
COUNT(p.product_id)
FROM
production.products p
INNER JOIN production.categories c
ON c.category_id = p.category_id
GROUP BY
c.category_id,
c.category_name
),
cte_category_sales(category_id, sales) AS (
SELECT
p.category_id,
SUM(i.quantity * i.list_price * (1 - i.discount))
FROM
sales.order_items i
INNER JOIN production.products p
ON p.product_id = i.product_id
INNER JOIN sales.orders o
ON o.order_id = i.order_id
WHERE order_status = 4 -- completed
GROUP BY
p.category_id
)
SELECT
c.category_id,
c.category_name,
c.product_count,
s.sales
FROM
cte_category_counts c
INNER JOIN cte_category_sales s
ON s.category_id = c.category_id
ORDER BY
c.category_name;
CTE đệ quy trong SQL Server

CTE đệ quy (recursive common table expression) là một CTE tham chiếu đến chính nó. Bằng cách làm như vậy, CTE lặp đi lặp lại thực thi, trả về các tập con dữ liệu, cho đến khi nó trả về tập kết quả hoàn chỉnh.
SQL CTE đệ quy hữu ích trong việc truy vấn dữ liệu phân cấp, chẳng hạn như biểu đồ tổ chức trong đó một nhân viên báo cáo với người quản lý hoặc hóa đơn nguyên vật liệu nhiều cấp khi một sản phẩm bao gồm nhiều thành phần và bản thân mỗi thành phần cũng bao gồm nhiều thành phần khác.
Sau đây là cú pháp của một CTE đệ quy:
WITH expression_name (column_list)
AS
(
-- Anchor member
initial_query
UNION ALL
-- Recursive member that references expression_name.
recursive_query
)
-- references expression name
SELECT *
FROM expression_name
CTE đệ quy có mấy phần?
Một CTE đệ quy có 3 phần:
- Truy vấn ban đầu trả về tập kết quả cơ bản của CTE. Truy vấn ban đầu được gọi là phần tử neo
Anchor member
. - Một truy vấn đệ quy tham chiếu đến CTE, do đó, nó được gọi là phần tử đệ quy
Recursive member
. Thành viên đệ quy được liên kết với thành viên neo bằng cách sử dụng toán tửUNION ALL
. - Một điều kiện kết thúc được chỉ định trong phần tử đệ quy kết thúc việc thực thi của phần tử đệ quy.
Thứ tự thực hiện CTE đệ quy là gì?
Thứ tự thực thi của một CTE đệ quy như sau:
- Đầu tiên, thực thi phần tử neo để tạo tập kết quả cơ sở (R0), sử dụng kết quả này cho lần lặp tiếp theo.
- Thứ hai, thực thi phần tử đệ quy với tập kết quả đầu vào từ lần lặp trước (Ri-1) và trả về tập kết quả phụ (Ri) cho đến khi điều kiện kết thúc được đáp ứng.
- Thứ ba, kết hợp tất cả các tập kết quả R0, R1,… Rn bằng cách sử dụng toán tử
UNION ALL
để tạo ra tập kết quả cuối cùng.
Ví dụ về CTE đệ quy SQL Server

Ví dụ này sử dụng một CTE đệ quy để trả về ngày trong tuần từ Monday
đến Saturday
:
WITH cte_numbers(n, weekday)
AS (
SELECT
0,
DATENAME(DW, 0)
UNION ALL
SELECT
n + 1,
DATENAME(DW, n + 1)
FROM
cte_numbers
WHERE n < 6
)
SELECT
weekday
FROM
cte_numbers;
Trong ví dụ này:
Hàm DATENAME()
trả về tên của các ngày trong tuần dựa trên một số ngày trong tuần.
Phần tử neo trả về Monday
SELECT
0,
DATENAME(DW, 0)
Phần tử đệ quy trả về kết quả từ ngày hôm sau bắt đầu từ Tuesday
đến Sunday
.
SELECT
n + 1,
DATENAME(DW, n + 1)
FROM
cte_numbers
WHERE n < 6
Điều kiện trong mệnh đề WHERE
là điều kiện kết thúc việc thực hiện phần tử đệ quy khi n là 6
n < 6
Common table expression là gì?

Common table expression SQL server (Structured Query Language) được sử dụng để đặt tên cho một truy vấn con và tái sử dụng nó trong một hoặc nhiều truy vấn lớn hơn.
CTE thường được sử dụng để làm cho các truy vấn phức tạp trở nên dễ đọc và quản lý hơn bằng cách chia chúng thành các phần nhỏ hơn và đặt tên cho chúng.
Common table expression mssql được đặt trong phần WITH của một truy vấn SQL và có thể được tham chiếu bởi các truy vấn SELECT, INSERT, UPDATE hoặc DELETE trong cùng một câu truy vấn lớn. Thông thường,
Common table expression (CTE) được sử dụng để thực hiện các phép tính như lặp, đệ quy. Hoặc đơn giản là để làm cho mã SQL trở nên dễ đọc hơn và dễ bảo trì hơn.
Recursive là gì?
Recursive hay đệ quy là khái niệm mà một hàm hoặc quy tắc có thể tự gọi chính nó để giải quyết một vấn đề. Quy tắc hoặc hàm đệ quy thường chia nhỏ vấn đề lớn thành các vấn đề nhỏ hơn, giải quyết chúng, và kết hợp các kết quả này để đạt được giải pháp cho vấn đề gốc.
Ví dụ đơn giản về hàm đệ quy có thể là tính giai thừa.
Window functions là tính năng mạnh mẽ trong SQL giúp thực hiện các phép toán trên một tập hợp con của dữ liệu được xác định thông qua một “cửa sổ” tương ứng với mỗi hàng kết quả.
Các window functions thường được sử dụng trong kết hợp với mệnh đề OVER để xác định cách các dòng dữ liệu được nhóm và sắp xếp trước khi thực hiện phép toán.
Kết lại
Trên đây là toàn bộ chia sẻ của Comdy.vn về CTE trong SQL server. Hi vọng những thông tin, kiến thức hữu ích trong bài viết này sẽ giúp bạn giải quyết các bài toán cơ sở dữ liệu một cách hiệu quả, chính xác nhất. Xin cám ơn vì đã dành thời gian theo dõi, ủng hộ bài viết.