Running total viết bằng SUM() OVER (ORDER BY ...).
Điểm bẫy là frame mặc định.
SELECT day, amount,
SUM(amount) OVER (ORDER BY day) AS running_total
FROM daily_sales;Khi có ORDER BY mà không viết frame, chuẩn SQL mặc định là RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. RANGE gom theo giá trị sắp xếp, nên mọi dòng cùng day đều nhận cùng một tổng — tổng đã bao gồm cả các dòng ngang hàng.
-- day: 1, 1, 2 amount: 10, 20, 5
-- RANGE (mac dinh): 30, 30, 35 <- hai dong ngay 1 deu la 30
-- ROWS: 10, 30, 35 <- cong lan luot tung dong
SUM(amount) OVER (ORDER BY day ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)Cách chọn:
- Muốn cộng dồn từng dòng một → viết rõ ROWS.
- Muốn tổng theo mốc thời gian (mọi giao dịch cùng ngày cho cùng số dư cuối ngày) → giữ RANGE.
- ROWS BETWEEN 6 PRECEDING AND CURRENT ROW cho trung bình trượt 7 dòng; RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT ROW cho trung bình trượt 7 ngày kể cả ngày trống.
Để tránh mơ hồ, nên luôn viết frame tường minh trong truy vấn báo cáo. ROWS cũng thường nhanh hơn vì không phải dò biên theo giá trị.