Cùng một hàm SUM. Có ORDER BY thì ra luỹ kế, không có thì ra tổng cả nhóm. Không ai nói cho bạn biết.
Bài toán
Biểu đồ cần đường doanh thu luỹ kế từ đầu tháng, và đường trung bình trượt 3 ngày để làm mượt.
Luỹ kế
SELECT
ngay,
doanh_thu,
SUM(doanh_thu) OVER (ORDER BY ngay) AS luy_ke
FROM doanh_thu_ngay;
Chi tiết quyết định tất cả
Chỉ khác một mệnh đề, ý nghĩa khác hẳn.
SUM(x) OVER () cho tổng toàn bộ.SUM(x) OVER (ORDER BY ngay) cho luỹ kế đến dòng hiện tại.Chỉ khác một mệnh đề, ý nghĩa khác hẳn.
Trung bình trượt
SELECT
ngay,
ROUND(AVG(doanh_thu) OVER (
ORDER BY ngay
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
), 1) AS tb_3_ngay
FROM doanh_thu_ngay;
ROWS BETWEEN định nghĩa “cửa sổ” — bao nhiêu dòng được tính vào:
| Viết | Nghĩa |
|---|---|
2 PRECEDING AND CURRENT ROW | 3 dòng gần nhất |
UNBOUNDED PRECEDING AND CURRENT ROW | từ đầu đến hiện tại (mặc định) |
1 PRECEDING AND 1 FOLLOWING | trước, hiện tại, sau |
CURRENT ROW AND UNBOUNDED FOLLOWING | từ hiện tại đến hết |
Lỗi thường gặp
1. Nhầm ROWS với RANGE
ROWS đếm số dòng. RANGE đếm theo giá trị, nên mọi dòng cùng ngày được gộp vào một bậc. Với dữ liệu có ngày trùng, hai cách cho kết quả khác nhau. Mặc định là RANGE — đây là nguồn gốc của nhiều con số khó hiểu.
2. Quên PARTITION BY
-- SAI: luỹ kế chạy xuyên qua mọi thành phố
SUM(doanh_thu) OVER (ORDER BY ngay)
-- ĐÚNG
SUM(doanh_thu) OVER (PARTITION BY thanh_pho ORDER BY ngay)
3. Ngày bị thiếu làm trung bình trượt sai
ROWS 2 PRECEDING lấy 3 dòng, không phải 3 ngày. Nếu thiếu ngày, cửa sổ trượt qua khoảng trống mà không ai biết. Tạo dải ngày đầy đủ trước khi tính.
Mẹo viết gọn khi dùng lại nhiều lần
SELECT
ngay,
SUM(doanh_thu) OVER w AS luy_ke,
AVG(doanh_thu) OVER w AS trung_binh,
MAX(doanh_thu) OVER w AS cao_nhat
FROM doanh_thu_ngay
WINDOW w AS (ORDER BY ngay);
Luyện tập
- LeetCode 1321 — Restaurant Growth (trung bình trượt 7 ngày)
- LeetCode 579 — Find Cumulative Salary of an Employee
- LeetCode 1204 — Last Person to Fit in the Bus
- LeetCode 534 — Game Play Analysis III
- HackerRank — Weather Observation Station 20 (median)
Tóm lại
ORDER BYtrongOVERbiếnSUMthành luỹ kế.ROWS BETWEENđịnh nghĩa cửa sổ trung bình trượt.ROWSđếm dòng,RANGEđếm theo giá trị — mặc định làRANGE.- Nhiều nhóm thì phải có
PARTITION BY. - Dùng
WINDOW w AS (…)khi lặp lại cùng một cửa sổ.
Bạn vừa học xong luỹ kế và trung bình trượt
Sẵn sàng luyện tập chưa?
Làm bài tập luỹ kế và trung bình trượt trên dữ liệu thật, chấm điểm ngay khi bạn bấm chạy.
Bắt đầu luyện tập →