Bài học theo mô-đun (1/4)
CTE: truy vấn nhiều bước với VỚI
Truy vấn thực có xu hướng tăng: ba JOIN, GROUP BY, truy vấn phụ,
một truy vấn phụ khác… và chúng trở nên không thể đọc được. CTE ("Bảng chung
Biểu thức", mệnh đề WITH) cho phép bạn đặt tên cho một
bước trung gian và sử dụng nó như thể nó là một bảng trong truy vấn chính.
Cú pháp cơ bản
WITH nome_cte AS (
SELECT … -- query interna
)
SELECT … -- query principale, usa nome_cte come fosse una tabella
FROM nome_cte;CTE hợp lệ chỉ dành cho truy vấn theo sau nó: nó không tồn tại việc hành quyết.
Ví dụ
Tìm 3 khách hàng đã chi tiêu nhiều nhất (tổng số đơn hàng đã giao):
WITH total_spent AS (
SELECT o.customer_id,
SUM(oi.quantity * oi.unit_price) AS total
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
WHERE o.status = 'delivered'
GROUP BY o.customer_id
)
SELECT c.email,
s.total
FROM total_spent s
JOIN customers c ON c.id = s.customer_id
ORDER BY s.total DESC
LIMIT 3;Đọc bằng tiếng Anh: "đầu tiên hãy tính chi tiêu cho mỗi khách hàng; sau đó kết hợp với
khách hàng và chiếm top 3". Nếu không có CTE, bạn sẽ cần một nội tuyến
truy vấn phụ trong FROM (hợp pháp nhưng ồn ào hơn).
Nhiều CTE theo tầng
Bạn có thể xác định nhiều CTE được phân tách bằng dấu phẩy và mỗi CTE có thể tham chiếu đến những cái trước:
WITH total_spent AS (
SELECT customer_id, SUM(quantity * unit_price) AS total
FROM order_items oi
JOIN orders o ON oi.order_id = o.id
WHERE o.status = 'delivered'
GROUP BY customer_id
),
average AS (
SELECT AVG(total) AS total_average
FROM total_spent
)
SELECT c.email, s.total
FROM total_spent s
JOIN customers c ON c.id = s.customer_id
CROSS JOIN average
WHERE s.total > average.total_average
ORDER BY s.total DESC;CROSS JOIN average vì average luôn có một hàng:
Tích Descartes chỉ thêm total_average vào mỗi hàng của kết quả.
CTE và truy vấn phụ: khi nào nên sử dụng cái nào
CTE tỏa sáng khi:
- cùng một truy vấn phụ được sử dụng hai lần trở lên trong truy vấn chính;
- bạn muốn làm cho cấu trúc rõ ràng trong các bước được đặt tên (tự ghi lại);
- chúng là điều kiện tiên quyết cho CTE đệ quy (
WITH RECURSIVE, bài học tiếp theo trong mô-đun này).
Truy vấn con nội tuyến sẽ ngắn gọn hơn đối với một bước chỉ được sử dụng một lần.
Hãy thử nó
Sử dụng CTE có tên là 'total_spent' để tính toán tổng chi tiêu (SUM(quantity * unit_price)) cho mỗi đơn hàng đã giao cho mỗi khách hàng. Sau đó, trong truy vấn chính hiển thị email và tổng số tiền cho 3 người chi tiêu nhiều nhất. Sắp xếp theo tổng số giảm dần, giới hạn ở mức 3.
Hiển thị gợi ý
Bên trong số lượng tổng CTE * đơn vị_giá. Trong truy vấn chính THAM GIA khách hàng trên id.
Giải pháp khả dụng sau 3 lần thử
Xem lại bài tập
CTE 'total_spent' giống như bài tập trước. Trong truy vấn chính, hiển thị email và tổng số tiền cho những khách hàng có mức chi tiêu cao hơn mức chi tiêu trung bình (trên tất cả các khách hàng có ít nhất một đơn hàng đã giao). Sắp xếp theo tổng giảm dần.
Hiển thị gợi ý
Truy vấn con vô hướng trong WHERE: SELECT AVG(total) FROM Total_spent.
Giải pháp khả dụng sau 3 lần thử