跳转到主要内容
模块 7 · 第 2 课(共 4)课程中的26/57~14 min
模块课程(2/4)

窗口函数:排名和每组计算

窗口函数是对“行组”进行操作的函数 (window)但是 - 与 GROUP BY 不同 - 不会减少 rows:在窗口上计算的值附加到每一行 最终结果。

它是排名、渐进编号、百分比的正确工具 超过一个组总数,以及许多其他尴尬或 对于 GROUP BY 是不可能的。

语法:function() OVER (…)

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

成分:

  • PARTITION BY — 定义“组”(如 GROUP BY,但行 保持分开);
  • ORDER BY inside OVER(…) — 定义内的顺序 分区。

OVER ()(空括号)表示“整个表作为单个窗口”。 对于“总数的百分比”等计算很有用。

排名功能

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)

差异(值为 100, 100, 90, 80):

功能职位
ROW_NUMBER1, 2, 3, 4(始终是唯一的)
RANKRANK 1, 1, 3, 4(关系共享一个位置,留下“间隙”)
DENSE_RANK1, 1, 2, 3(关系共享一个位置,无间隙)

示例:每个类别的产品排名

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;

对于每个 category_id , RANK 从 1 重新开始并按降序排列 价格:您可以在一个类别中每个类别内的产品排名 射击。

渐进编号

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;

每个客户的第一个订单将具有 row_num = 1,第二个订单将具有 2,依此类推。

尝试一下

锻炼#sql.m7.l2.e1
尝试:0加载中...

对于每个产品,显示名称、category_id、价格和排名(按类别内价格降序排名;使用 RANK)。按类别_id 升序和排名升序排序。

正在加载编辑器...
显示提示

PARTITION BYcategory_id 组,ORDER BY 组内价格 DESC 订单。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m7.l2.e2
尝试:0加载中...

对于每个订单,显示 id、customer_id、ordered_at 和 row_num(每个客户的渐进 ROW_NUMBER,按 ordered_at 升序排序)。按 customer_id 和 row_num 排序。

正在加载编辑器...
显示提示

ROW_NUMBER 在分区内始终是唯一的。

3 次尝试后可用的解决方案