Day 11 - Pro: Window Functions
Bối cảnh: Hệ thống E-commerce (Thương mại điện tử)
1. OVER() with PARTITION BY
Window Functions: Cho phép thực hiện tính toán trên một tập hợp các hàng liên quan đến hàng hiện tại mà không làm gộp chúng thành một hàng duy nhất.
PARTITION BY: Chia dữ liệu thành các nhóm (partition) để áp dụng hàm cửa sổ.
Ví dụ: Tính tổng doanh thu theo từng phương thức thanh toán:
SELECT order_id, payment_method, total_amount, SUM(total_amount) OVER (PARTITION BY payment_method) AS total_revenue_by_method FROM orders;
Kết quả trả về tổng doanh thu của từng phương thức thanh toán cho mỗi đơn hàng.
2. Challenge: OVER() with PARTITION BY
- Yêu cầu: Viết truy vấn để tính tổng số lượng sản phẩm (total_quantity) đã bán theo từng danh mục (category) từ bảng orders và products.
3. Solution: OVER() with PARTITION BY
Giải pháp:
SELECT o.order_id, p.category, o.quantity, SUM(o.quantity) OVER (PARTITION BY p.category) AS total_quantity_by_category FROM orders o INNER JOIN products p ON o.product_id = p.product_id;
4. OVER() with ORDER BY
ORDER BY trong Window Functions: Sắp xếp dữ liệu trong partition trước khi áp dụng hàm.
Ví dụ: Tính tổng doanh thu tích lũy theo thời gian:
SELECT order_id, order_date, total_amount, SUM(total_amount) OVER (ORDER BY order_date) AS cumulative_revenue FROM orders;
Kết quả trả về tổng doanh thu tích lũy theo từng ngày đặt hàng.
5. Challenge: OVER() with ORDER BY
- Yêu cầu: Viết truy vấn để xếp hạng (rank) các sản phẩm theo số lượng bán (quantity) giảm dần.
6. Solution: OVER() with ORDER BY
Giải pháp:
SELECT product_id, quantity, RANK() OVER (ORDER BY quantity DESC) AS sales_rank FROM orders;
7. RANK()
RANK(): Xếp hạng các hàng dựa trên giá trị của một cột. Nếu có giá trị trùng nhau, các hàng tiếp theo sẽ nhảy bậc.
Ví dụ: Xếp hạng khách hàng theo tổng giá trị đơn hàng:
SELECT customer_id, total_amount, RANK() OVER (ORDER BY total_amount DESC) AS customer_rank FROM orders;
8. Challenge: RANK()
- Yêu cầu: Xếp hạng các danh mục sản phẩm (category) theo tổng doanh thu (total_amount) giảm dần.
9. Solution: RANK()
Giải pháp:
SELECT p.category, SUM(o.total_amount) AS total_revenue, RANK() OVER (ORDER BY SUM(o.total_amount) DESC) AS revenue_rank FROM orders o INNER JOIN products p ON o.product_id = p.product_id GROUP BY p.category;
10. FIRST_VALUE()
FIRST_VALUE(): Trả về giá trị đầu tiên trong một partition.
Ví dụ: Tìm ngày đặt hàng đầu tiên của mỗi khách hàng:
SELECT customer_id, order_date, FIRST_VALUE(order_date) OVER (PARTITION BY customer_id ORDER BY order_date) AS first_order_date FROM orders;
11. LEAD & LAG
LEAD(): Truy cập giá trị của hàng tiếp theo trong partition.
LAG(): Truy cập giá trị của hàng trước đó trong partition.
Ví dụ: So sánh doanh thu giữa các tháng:
SELECT EXTRACT(MONTH FROM order_date) AS month, SUM(total_amount) AS monthly_revenue, LAG(SUM(total_amount)) OVER (ORDER BY EXTRACT(MONTH FROM order_date)) AS prev_month_revenue, LEAD(SUM(total_amount)) OVER (ORDER BY EXTRACT(MONTH FROM order_date)) AS next_month_revenue FROM orders GROUP BY month;
12. Challenge: LEAD & LAG
- Yêu cầu: Tính chênh lệch doanh thu giữa tháng hiện tại và tháng trước đó.
13. Solution: LEAD & LAG
Giải pháp:
WITH monthly_revenue AS ( SELECT EXTRACT(MONTH FROM order_date) AS month, SUM(total_amount) AS current_month_revenue FROM orders GROUP BY month ) SELECT month, current_month_revenue, LAG(current_month_revenue) OVER (ORDER BY month) AS prev_month_revenue, current_month_revenue - LAG(current_month_revenue) OVER (ORDER BY month) AS revenue_diff FROM monthly_revenue;
14. Today's slides
Tổng kết các hàm cửa sổ: PARTITION BY, ORDER BY, RANK(), FIRST_VALUE(), LEAD(), LAG().
Slide tham khảo cung cấp ví dụ chi tiết và ứng dụng trong hệ thống E-commerce.
15. Today's summary
Hôm nay, bạn đã học:
Cách sử dụng PARTITION BY và ORDER BY trong Window Functions.
Cách xếp hạng dữ liệu với RANK().
Cách truy cập giá trị đầu tiên (FIRST_VALUE()) và so sánh dữ liệu giữa các hàng (LEAD(), LAG()).
Hẹn gặp lại bạn vào ngày 12 với chủ đề Pro: Grouping sets, rollups, self-joins!
16. Today's challenges
Thử thách 1: Tính tỷ lệ phần trăm đóng góp doanh thu của từng sản phẩm trong tổng doanh thu của danh mục.
Thử thách 2: Xếp hạng khách hàng (customer_id) theo tổng số lượng đơn hàng (order_count) giảm dần.
Thử thách 3: Tìm khoảng thời gian (số ngày) giữa hai đơn hàng liên tiếp của cùng một khách hàng.