Chuyển đến nội dung chính
Mô-đun 7 · Bài học 2 trong tổng số 426/57 trong khóa học~14 min
Bài học theo mô-đun (2/4)

Chức năng cửa sổ: xếp hạng và tính toán theo nhóm

Hàm cửa sổ là một hàm hoạt động trên một "nhóm hàng" (cửa sổ) nhưng — không giống GROUP BY — không làm giảm số lượng hàng: một giá trị được tính toán trên cửa sổ được gắn vào mỗi hàng của kết quả cuối cùng.

Đây là công cụ phù hợp để xếp hạng, đánh số lũy tiến, tỷ lệ phần trăm trên tổng số nhóm và nhiều thao tác khác khó xử lý hoặc không thể với GROUP BY.

Cú pháp: function() OVER (…)

SQL
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)

thành phần:

  • PARTITION BY — xác định các "nhóm" (như GROUP BY, nhưng các hàng ở riêng);
  • ORDER BY bên trong OVER(…) — xác định thứ tự trong phân vùng.

OVER () (dấu ngoặc đơn trống) có nghĩa là "toàn bộ bảng dưới dạng một cửa sổ". Hữu ích cho các phép tính như "phần trăm của tổng số".

Chức năng xếp hạng

SQL
ROW_NUMBER() OVER (PARTITION BY p ORDER BY o)
RANK()       OVER (PARTITION BY p ORDER BY o)
DENSE_RANK() OVER (PARTITION BY p ORDER BY o)

Sự khác biệt (với các giá trị 100, 100, 90, 80):

Chức năngVị trí
ROW_NUMBER1, 2, 3, 4 (luôn duy nhất)
RANK1, 1, 3, 4 (quan hệ chia sẻ vị trí, để lại "khoảng trống")
DENSE_RANK1, 1, 2, 3 (các mối quan hệ có chung một vị trí, không có khoảng trống)

Ví dụ: xếp hạng sản phẩm theo danh mục

SQL
SELECT name,
       category_id,
       price,
       RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS rank
FROM   products
ORDER BY category_id, rank;

Đối với mỗi category_id RANK khởi động lại từ 1 và sắp xếp theo thứ tự giảm dần giá: bạn có được thứ hạng của sản phẩm trong mỗi danh mục, trong một bắn.

Đánh số lũy tiến

SQL
-- Progressive order number for each customer:
SELECT id,
       customer_id,
       ordered_at,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY ordered_at) AS row_num
FROM   orders
ORDER BY customer_id, row_num;

Đơn hàng đầu tiên của mỗi khách hàng sẽ có row_num = 1, 2 thứ hai, v.v.

Hãy thử nó

tập thể dục#sql.m7.l2.e1
Nỗ lực: 0Đang tải…

Đối với mỗi sản phẩm, hãy hiển thị tên, id danh mục, giá và thứ hạng (xếp hạng theo giá giảm dần TRONG danh mục; sử dụng RANK). Sắp xếp theo thứ hạng tăng dần Category_id và thứ hạng tăng dần.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

THAM GIA THEO nhóm danh mục_id, ĐẶT HÀNG THEO giá DESC đơn hàng trong nhóm.

Giải pháp khả dụng sau 3 lần thử

Xem lại bài tập

tập thể dục#sql.m7.l2.e2
Nỗ lực: 0Đang tải…

Đối với mỗi đơn hàng, hãy hiển thị id, customer_id, order_at và row_num (ROW_NUMBER lũy tiến cho mỗi khách hàng, được sắp xếp theo thứ tự tăng dần). Đặt hàng theo customer_id và row_num.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

ROW_NUMBER luôn là duy nhất trong phân vùng.

Giải pháp khả dụng sau 3 lần thử