select order_id,
customer_name,
order_date
from (
select order_id,
customer_name,
order_date,
rank() over (partition by customer_name order by order_date desc) rk
from orders d join customers c using(customer_id)
) t
where rk=1
1.窗口函数要用rank(),而不是max()
- 第一段代码:使用 max(order_date) over (partition by customer_name order by order_date) 窗口函数。按 customer_name 分区(即每个客户单独分组),并按 order_date 升序排序,在分区内计算每个行对应的最大 order_date 。最终查询结果里,同一客户的多条记录会重复显示该客户最大订单日期(因为窗口函数是为每行生成结果 )。例如,若客户 A 有 3 条订单记录,日期分别是 2025-01-01、2025-01-02、2025-01-03 ,则这 3 行的 order_date (通过窗口函数计算后)都会显示 2025-01-03 。
- 第二段代码:用 rank() over (partition by customer_name order by order_date desc) 窗口函数。同样按 customer_name 分区,不过按 order_date 降序 排序,为分区内每行记录计算排名(rk )。结合外部 where rk = 1 条件,最终会筛选出每个客户 订单日期最新(最大) 的那一条记录 。延续上面客户 A 的例子,按降序排序列表是 2025-01-03(rk=1 )、2025-01-02(rk=2 )、2025-01-01(rk=3 ),where rk=1 就只会保留 2025-01-03 对应的那行数据。
- 第一段代码:结果集可能包含同一客户的多条记录,且这些记录的 order_date (窗口函数计算后的值)都等于该客户最大订单日期,数据会有冗余重复。
- 第二段代码:结果集是 每个客户仅保留 1 条记录 ,即对应其订单日期最新(rk=1 )的那条订单数据,结果更简洁,精准筛选出每个客户的最新订单。
max(...) over(...)是 窗口聚合函数 ,作用是在分区内为每行计算一个聚合值(这里是最大日期 ),不改变结果集行数。rank() over(...)是 窗口排名函数 ,会为分区内每行生成排名序号,搭配where条件可实现行筛选,能减少结果集行数
1. 分析函数及作用逻辑
2. 最终结果形态
3. 函数本质区别
简单说,第一段是 “标记” 出每个客户的最大订单日期(保留所有行),第二段是 “筛选” 出每个客户最大订单日期对应的那一行,功能和结果差异明显。
2.用rank的序号筛选输出可以实现和group by一样的效果,因为他每个区内部也是只有唯一一个序号

京公网安备 11010502036488号