Master Window Function trong SQL: Bí Kíp Tối Ưu Phân Tích Dữ Liệu
Source: Dev.to

Chào anh em Data và Backend! Khi làm việc với SQL, chắc hẳn ai cũng đã quá quen với GROUP BY. Dù rất mạnh mẽ, nhưng GROUP BY có một nhược điểm chí mạng: nó “gom” các dòng lại và làm mất đi chi tiết của từng dòng dữ liệu gốc.
Nếu sếp yêu cầu: “Lấy ra chi tiết từng đơn hàng, kèm theo tổng doanh thu của cả tháng đó trên cùng một dòng” thì sao? Đó là lúc Window Function (hàm cửa sổ) tỏa sáng!
1. Window Function là gì?
Window Function 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 (gọi là “cửa sổ”) mà không làm thay đổi số lượng hàng trả về.
Cấu trúc cơ bản
Để SQL biết bạn đang dùng Window Function, phải có mệnh đề OVER(). Bên trong OVER() thường chứa:
PARTITION BY– chia dữ liệu thành các nhóm (giốngGROUP BYnhưng không gộp dòng).ORDER BY– sắp xếp dữ liệu trong mỗi nhóm.ROWS/RANGE– định nghĩa khung cửa sổ hẹp hơn (ví dụ: chỉ tính tổng của 3 dòng gần nhất).
2. Các loại Window Function “nhẵn mặt”
A. Hàm tổng hợp (Aggregate Window Functions)
Vẫn là SUM, AVG, COUNT, MAX, MIN nhưng được dùng kèm OVER().
Ví dụ: Tính tổng lũy kế doanh thu theo từng ngày trong năm
SELECT
MaDonHang,
NgayDatHang,
TongTien,
SUM(TongTien) OVER (
PARTITION BY YEAR(NgayDatHang)
ORDER BY NgayDatHang
) AS TongLuyKeNam
FROM DonHang;
B. Hàm xếp hạng (Ranking Window Functions)
Hữu ích để tìm “Top N” sản phẩm, nhân viên xuất sắc.
| Hàm | Mô tả |
|---|---|
ROW_NUMBER() | Đánh số thứ tự liên tục 1, 2, 3, … (không quan tâm giá trị trùng). |
RANK() | Đồng hạng khi giá trị bằng nhau, nhưng bỏ qua thứ hạng tiếp theo (VD: 1, 2, 2, 4). |
DENSE_RANK() | Đồng hạng nhưng không bỏ qua thứ hạng tiếp theo (VD: 1, 2, 2, 3). |
Ví dụ: Xếp hạng sản phẩm bán chạy nhất trong từng danh mục
SELECT
DanhMuc,
TenSanPham,
TongSoLuongBan,
RANK() OVER (
PARTITION BY DanhMuc
ORDER BY TongSoLuongBan DESC
) AS HangSanPham
FROM SanPhamBanChay;
C. Hàm giá trị (Value Window Functions)
Lấy giá trị của dòng trước hoặc dòng sau so với dòng hiện tại – rất hữu ích cho các phép tính biến động (MoM, YoY).
LAG()– lấy giá trị của dòng phía trước.LEAD()– lấy giá trị của dòng phía sau.
Ví dụ: So sánh doanh số tháng này với tháng trước
SELECT
Thang,
DoanhSo,
LAG(DoanhSo, 1, 0) OVER (ORDER BY Thang) AS DoanhSoThangTruoc,
DoanhSo - LAG(DoanhSo, 1, 0) OVER (ORDER BY Thang) AS ChenhLech
FROM BaoCaoDoanhSo;
3. Bí kíp tối ưu hiệu suất
- Index là chân ái – Đảm bảo các cột dùng trong
PARTITION BYvàORDER BYđã được đánh index phù hợp; nếu không DB sẽ phải sắp xếp thủ công, tốn tài nguyên. - Hạn chế window frame quá rộng – Tránh dùng
UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGtrên tập dữ liệu khổng lồ nếu không thực sự cần. - Kết hợp với CTE (
WITH ... AS) – Khi cần nhiều Window Function phức tạp, tách chúng ra bằng CTE giúp code dễ đọc và DB tối ưu Execution Plan tốt hơn.
🎯 Tóm lại
Thay vì viết những subquery dài, chạy chậm, Window Function mang đến cú pháp thanh lịch và tốc độ thực thi vượt trội. Đối với các công việc Data Analysis hay Backend xử lý báo cáo, đây là kỹ năng bắt buộc.
Khám phá thêm: Nếu muốn luyện tập các bài toán SQL, tối ưu truy vấn hoặc Database Design, hãy ghé thăm blog ITPrep để nâng cấp bộ kỹ năng ngay hôm nay!
Nguồn tham khảo: ITPrep – Hướng dẫn chuyên sâu về Window Function trong SQL