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

MSSQL分组取Top-N:如何快速获取各品类Top10高价商品?

高效获取MSSQL中每个类别Top10最贵商品的方案

嘿,针对你手里1万到100万条商品数据的场景,要快速揪出每个类别下最贵的10件商品,我得给你推荐几个经过实战验证的高效方法——毕竟数据量不小,慢查询可是会拖垮系统的!

最优方案:窗口函数ROW_NUMBER() + 覆盖索引

这绝对是大数据量下的首选,MSSQL对窗口函数的优化做得非常到位,再配上合适的索引,速度快到飞起。

第一步:先建关键索引(敲黑板!这是性能提升的核心)

首先给你的商品表创建一个覆盖索引,让数据库不用回表就能拿到所有需要的数据:

CREATE NONCLUSTERED INDEX IX_Product_Category_Price
ON dbo.Product (category ASC, price DESC)
INCLUDE (product_id, name); -- 把需要返回的字段都包含进来,避免额外的键查找

这个索引是按category分组,同类别下按price降序排列,数据库可以直接顺着索引读取每个类别的前10条数据,完全不需要额外排序。

第二步:写查询语句

用CTE(公共表表达式)结合ROW_NUMBER()窗口函数,逻辑清晰又高效:

WITH RankedProducts AS (
    SELECT 
        product_id,
        name,
        category,
        price,
        -- 按类别分组,价格降序排名,每个类别里的商品从1开始编号
        ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS PriceRank
    FROM dbo.Product
)
SELECT 
    product_id,
    name,
    category,
    price
FROM RankedProducts
WHERE PriceRank <= 10 -- 只取每个类别前10名
ORDER BY category, price DESC;

为什么这个方法快?因为索引已经帮我们把数据排好序了,查询时数据库只需要扫描一次索引,就能直接筛选出符合条件的记录,时间复杂度接近O(n),100万条数据也能秒出结果。

兼容旧版本的备选方案:关联子查询

如果你还在使用MSSQL 2008及更早的版本(不过现在应该很少了),可以用关联子查询的方式实现,但性能会比窗口函数差不少,尤其是数据量越大差距越明显:

SELECT 
    p1.product_id,
    p1.name,
    p1.category,
    p1.price
FROM dbo.Product p1
WHERE 10 > (
    -- 统计当前类别中价格比当前商品高的数量,小于10说明是前10
    SELECT COUNT(*)
    FROM dbo.Product p2
    WHERE p2.category = p1.category AND p2.price > p1.price
)
ORDER BY p1.category, p1.price DESC;

这个方法的问题在于,每条记录都要执行一次子查询,数据量到100万时,查询时间会显著增加,所以优先选窗口函数方案。

性能小贴士

  • 定期更新表的统计信息:UPDATE STATISTICS dbo.Product;,让查询优化器能生成最优的执行计划。
  • 如果你的表经常有插入、更新操作,可以考虑给索引设置适当的填充因子,避免频繁的页拆分。
  • 测试时可以查看执行计划,确认查询是否用到了我们创建的覆盖索引——如果看到“索引扫描”而不是“索引查找”,那就要检查索引是否正确了。

内容的提问来源于stack exchange,提问作者Mr. 13

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:32:38