You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server如何选取每个partition内max row number对应的行

示例数据参考

可行解决方案

核心约束前置:无显式时间/自增序列字段、必须严格匹配数据插入顺序、需兼容Name字段为NULL的分区场景,禁止依赖倒序排序取首行的绕路逻辑。

方案1:基于原生窗口函数的物理顺序定位(兼容MySQL8.0+、PostgreSQL、Spark SQL、Hive等所有支持窗口函数的引擎)

核心逻辑是窗口函数内不指定ORDER BY字段,此时窗口函数生成的行号严格匹配数据的物理读取顺序,也就是要求的插入顺序;同时分区逻辑会自动将所有Name为NULL的记录归为同一个独立分区,天然覆盖NULL场景。
示例代码:

WITH ranked_records AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY Name) AS rn,
        COUNT(*) OVER (PARTITION BY Name) AS partition_total_cnt
    FROM your_target_table
)
SELECT * 
FROM ranked_records 
WHERE rn = partition_total_cnt;

注意:如果是Hive/Spark这类大数据引擎,执行时不要开启会打乱物理顺序的随机分区、重分区配置,否则会导致插入顺序错乱。

方案2:老版本引擎兼容方案(适配MySQL5.x等不支持窗口函数的场景)

通过会话变量模拟分区行号计数,全程不指定排序规则保留原生插入顺序:

SELECT * FROM (
    SELECT 
        t.*,
        @rn := IF(@current_name = Name OR (@current_name IS NULL AND Name IS NULL), @rn + 1, 1) AS rn,
        @current_name := Name AS dummy
    FROM your_target_table t, (SELECT @rn := 0, @current_name := NULL) AS init
) AS ranked
WHERE rn = (
    SELECT COUNT(*) FROM your_target_table t2 
    WHERE t2.Name = ranked.Name OR (t2.Name IS NULL AND ranked.Name IS NULL)
);

注意:该写法在老版本MySQL中需要关闭ONLY_FULL_GROUP_BY相关的严格模式校验,子查询内不要加任何ORDER BY逻辑,避免打乱原生插入顺序。

关键注意点

  • 所有NULL值的Name记录会被自动归为同一个分区,不需要额外写IFNULL/COALESCE类的转换逻辑,额外转换反而可能把NULL值和正常重名值混淆
  • 全程不要在计数逻辑外层加任何排序、重分布操作,否则会破坏原生插入顺序
  • 如果使用SQL Server这类默认会对无序查询做执行计划优化的引擎,需要加WITH (NOLOCK, INDEX(0))表提示强制按堆表物理顺序读取,避免优化器打乱顺序

内容的提问来源于stack exchange,提问作者Roli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:54:40