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

如何高效编写SQL获取表中第N高主键ID?两种写法哪种更优

第N高Customer_Id查询方案性能分析与优化

现有两种方案性能对比

你提供的两种查询语句如下:

-- 方案A
select top 1 Customer_Id
from customers c
where c.Customer_Id not in(
    select top 2 cc.Customer_Id
    from customers cc
    order by cc.Customer_Id desc
    )
order by c.Customer_Id desc
-- 方案B
select top 1 temp.Customer_Id
from (
      select top 3 c.Customer_Id
      from customers c
      order by c.Customer_Id desc) as temp
order by temp.Customer_Id
  • 性能上方案B远优于方案A:
    方案A使用NOT IN子查询实现排除前2高的ID,需要额外做一次主键值的匹配校验,当表数据量较大时,这部分匹配开销会明显上升。
    方案B仅做了两次有序的TOP N扫描,因为Customer_Id是主键,自带有序B+树索引,两次扫描都可以直接走索引,不需要额外匹配操作,开销远低于方案A。

更通用的高性能实现方案

针对适配任意第N高ID的需求,推荐使用以下两种兼容性更强、性能更优的写法:

1. OFFSET FETCH 写法(主流数据库通用,最简洁)

SQL Server 2012+、PostgreSQL、MySQL 8.0+等主流关系型数据库都支持该语法,只需要修改OFFSET后的数值即可调整取第几高的ID,第N高对应OFFSET为N-1:

-- 取第3高ID写法,要取第N高就把OFFSET后的2改为N-1
SELECT Customer_Id
FROM customers
ORDER BY Customer_Id DESC
OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY;

该写法可以让数据库优化器直接定位到主键索引降序的第N行,不需要额外的子查询或排序操作,性能最优。

2. 窗口函数写法(支持复杂排名规则)

如果需求涉及并列排名(比如两个相同ID算同一名次),可以使用窗口函数实现,灵活性更高:

-- 无并列排名需求用ROW_NUMBER,有并列同排名需求用DENSE_RANK
WITH ranked_customers AS (
    SELECT 
        Customer_Id,
        ROW_NUMBER() OVER(ORDER BY Customer_Id DESC) AS rank_num
    FROM customers
)
-- 取第3高就把rank_num = 3的3改为对应N值
SELECT Customer_Id FROM ranked_customers WHERE rank_num = 3;

该写法同样可以走主键索引,仅需一次全表索引扫描即可完成排名,性能也远高于嵌套子查询写法。

内容的提问来源于stack exchange,提问作者חיים חדד

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:21:03