假设存在产品表products
,包含字段:
product_id
(产品ID)category_id
(分类ID)product_name
(产品名称)需求逻辑:
WITH ranked_products AS ( SELECT product_id, category_id, product_name, ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY product_id) AS row_num FROM products ) SELECT product_id, category_id, product_name FROM ranked_products WHERE row_num <= 10;
特性:利用窗口函数实现高效分组编号,需注意版本兼容性
SELECT product_id, category_id, product_name FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY product_id) AS row_num FROM products ) AS subquery WHERE row_num <= 10;
提示:支持CTE表达式,适合处理复杂嵌套查询
SELECT product_id, category_id, product_name FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY product_id) AS rank FROM products ) AS temp_table WHERE rank <= 10;
扩展功能:可结合RANK()
或DENSE_RANK()
处理并列排名场景
适用于旧版本MySQL(5.7及以下):
SELECT p1.product_id, p1.category_id, p1.product_name FROM products p1 WHERE ( SELECT COUNT(*) FROM products p2 WHERE p2.category_id = p1.category_id AND p2.product_id <= p1.product_id ) <= 10 ORDER BY category_id, product_id;
注意事项:当数据量超过1万条时可能出现性能瓶颈
SELECT category_id, COUNT(*) FROM ( -- 上述查询语句 ) AS result GROUP BY category_id HAVING COUNT(*) != 10;
EXPLAIN
分析执行计划,确保索引有效使用问题类型 | 典型表现 | 解决方案 |
---|---|---|
重复记录 | 返回超过10条 | 检查ORDER BY 字段的唯一性 |
性能低下 | 查询超时 | 为category_id 建立复合索引 |
空分类 | 缺失部分分类 | 使用LEFT JOIN 关联分类表 |
优化建议:
category_id
和排序字段建立联合索引SET @num := 10; -- 在查询语句中使用@num变量
ORDER BY RAND()
PARTITION BY
的分区字段引用说明
本文涉及的技术实现参考以下官方文档: