MySQL中ROW_NUMBER() OVER的用法以及使用场景

发布于:2025-05-01 ⋅ 阅读:(20) ⋅ 点赞:(0)

使用语法

ROW_NUMBER() OVER (
  [PARTITION BY partition_column1, partition_column2, ...]
  ORDER BY sort_column1 [ASC|DESC], sort_column2 [ASC|DESC], ...
)
  • PARTITION BY:将数据按指定列分组,每组内单独生成行号。
  • ORDER BY:决定组内行号的排序依据。

适用场景

1. 分页查询

在需要对结果集分页且需要全局排序时,ROW_NUMBER() 可替代传统 LIMIT/OFFSET,尤其在复杂排序或嵌套查询中更高效。

SELECT *
FROM (
  SELECT 
    ROW_NUMBER() OVER (ORDER BY create_time DESC) AS row_num,
    id, title, create_time
  FROM articles
) AS tmp
WHERE row_num BETWEEN 11 AND 20; -- 获取第2页(每页10条)

2. 去重(保留每组最新/第一条记录)

当数据有重复时,按业务逻辑保留每组中的特定行(如最新记录)。

WITH ranked_data AS (
  SELECT 
    id, user_id, order_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id 
      ORDER BY order_date DESC
    ) AS rn
  FROM orders
)
SELECT id, user_id, order_date
FROM ranked_data
WHERE rn = 1; -- 每个用户最近的一笔订单

3. 生成唯一排名(无并列排名)

即使值相同,ROW_NUMBER() 也会生成唯一序号(区别于 RANK() 和 DENSE_RANK())。

SELECT 
  student_id, exam_score,
  ROW_NUMBER() OVER (ORDER BY exam_score DESC) AS rank
FROM exam_results; -- 分数相同的学生会得到不同排名

4. 分组分析(如时间序列处理)

按分区跟踪行号,用于分析组内趋势(如计算用户行为序列

SELECT 
  user_id, event_time, event_type,
  ROW_NUMBER() OVER (
    PARTITION BY user_id 
    ORDER BY event_time
  ) AS action_seq
FROM user_events; -- 标记用户行为的顺序

注意事项:

去重替代方案:若仅需去重,可考虑 DISTINCTGROUP BY,但复杂逻辑仍需 ROW_NUMBER()。


网站公告

今日签到

点亮在社区的每一天
去签到