Hàm cửa sổ (window function) trong Hive cho phép thực hiện tính toán trên tập hợp các hàng liên quan đến hàng hiện tại mà không làm mất cấu trúc bảng gốc. Dưới đây là phân tích chi tiết về một số hàm phổ biến cùng sự khác biệt then chốt giữa hai kiểu khung tính toán: ROWS và RANGE.
Hàm FIRST_VALUE
Hàm này trả về giá trị đầu tiên trong khung cửa sổ đã được sắp xếp:
SELECT
customer_id,
transaction_amount,
FIRST_VALUE(transaction_amount)
OVER (PARTITION BY customer_id ORDER BY transaction_amount) AS min_per_customer
FROM sales_data;
Kết quả cho thấy giá trị nhỏ nhất trong mỗi nhóm khách hàng được lặp lại cho mọi hàng thuộc nhóm đó — vì khung được sắp theo thứ tự tăng dần và FIRST_VALUE luôn chọn phần tử đầu tiên của khung.
Hàm tổng tích lũy với SUM và ảnh hưởng của khung tính toán
Khi không chỉ định rõ kiểu khung, Hive mặc định sử dụng RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. Điều này có nghĩa là tất cả các hàng có cùng giá trị transaction_amount như hàng hiện tại đều được đưa vào phép tính:
SELECT
customer_id,
transaction_amount,
SUM(transaction_amount)
OVER (PARTITION BY customer_id ORDER BY transaction_amount) AS cumulative_sum_range
FROM sales_data;
Ví dụ: Với ba giao dịch [150, 150, 200] trong cùng nhóm, khi xử lý hàng thứ hai (150), khung RANGE bao gồm cả hai giá trị 150 → tổng = 300; khi xử lý hàng thứ ba (cũng 150), khung vẫn giữ nguyên → tổng vẫn là 300. Do đó, hai hàng cùng giá trị sẽ có cùng kết quả tổng tích lũy.
Ngược lại, khi dùng ROWS, khung được xác định dựa trên vị trí vật lý (số thứ tự hàng sau khi sắp xếp), không phụ thuộc vào giá trị:
SELECT
customer_id,
transaction_amount,
SUM(transaction_amount)
OVER (PARTITION BY customer_id ORDER BY transaction_amount
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sum_rows
FROM sales_data;
Kết quả là tổng tuần tự theo thứ tự dòng: hàng 1 → giá trị hàng 1; hàng 2 → tổng hàng 1 + hàng 2; hàng 3 → tổng ba hàng đầu… Không có hiện tượng "nhảy cóc" do trùng giá trị.
Hàm truy cập hàng liền kề: LEAD và LAG
LEAD(column, offset, default) lấy giá trị từ hàng phía sau cách hàng hiện tại offset vị trí. Nếu vượt ngoài phạm vi, trả về giá trị mặc định (hoặc NULL nếu không khai báo):
SELECT
customer_id,
transaction_amount,
LEAD(transaction_amount, 2, -1)
OVER (PARTITION BY customer_id ORDER BY transaction_date) AS next_next_amount
FROM sales_data;
LAG(column, offset, default) hoạt động tương tự nhưng trỏ về phía trước — tức là lấy giá trị từ hàng phía trên:
SELECT
customer_id,
transaction_amount,
LAG(transaction_amount, 1, 0)
OVER (PARTITION BY customer_id ORDER BY transaction_date) AS previous_amount
FROM sales_data;
Cả hai hàm đều yêu cầu mệnh đề ORDER BY rõ ràng để đảm bảo thứ tự xác định, đặc biệt quan trọng khi phân tích chuỗi thời gian hoặc so sánh chênh lệch giữa các lần giao dịch.