586. 订单最多的用户
586. 订单最多的用户
难度:简单 | 题号:586 | 链接:586. 订单最多的客户 - 力扣(LeetCode) | 数据结构:SQL
关联:从不订购的用户(同用 Orders 表,一文求"从未下单",一文求"下单最多")· 分数排名(同为「分组计数 + 排名」题)· 可对照 SQL原理_03(CTE 写法)与 SQL原理_02(窗口函数)。
🎯 问题描述
描述:查找订单数量最多的客户的 customer_number。测试用例保证订单最多的客户只有一个。
表:Orders
1 | +-----------------+----------+ |
示例 1:
1 | 输入: |
提示:
- 先「按客户分组计数」,再「取计数最大的那一组」——本质是分组 Top-1。
- 题目只保证「唯一」,但追问要求能处理并列第一的情况(见思路 2)。
- 返回结果只有一列
customer_number。
💻 解题思路
思路1:GROUP BY + ORDER BY … LIMIT 1(用户解法)
核心逻辑
第一步按 customer_number 分组,COUNT(*) 数出每人订单数;第二步按订单数降序排,LIMIT 1 取第一名。用 CTE(WITH)把这两步拆开,可读性更好。
代码实现
1 | # Write your MySQL query statement below |
也可以省掉 CTE 一步写完:
SELECT customer_number FROM Orders GROUP BY customer_number ORDER BY COUNT(*) DESC LIMIT 1;
📊 性能分析
- 时间复杂度:(
GROUP BY聚合后对结果排序,排序是主导项;走主键索引可直接扫描计数)。 - 空间复杂度:(分组结果的哈希/临时表)。
思考
LIMIT 1的并列陷阱:如果多个客户并列最多,LIMIT 1只返回其中一个,且返回哪一个不确定(取决于排序稳定性)。本题靠「唯一」保证兜底才安全。- 评论区常见报错:聚合函数不能嵌套,
MAX(COUNT(*))是非法的 → 要么先聚合再排序取首,要么把计数做成子查询再取MAX。
思路2:窗口函数 DENSE_RANK(应对并列 · Follow-up)
核心逻辑
对每个客户的订单数排名,取 ranking = 1 的全部客户。并列第一时这里会全部保留,正好回答题目的追问「如果订单最多的客户有多个怎么办」。
代码实现
1 | SELECT customer_number |
📊 性能分析
- 时间复杂度:(分组 + 窗口排序)。
- 空间复杂度:。
- 与思路 1 同阶,但语义更强(天然处理并列),代价是写法更重。
思考
RANK()/DENSE_RANK()在并列时都会给出1;差别在后续名次(RANK跳号、DENSE_RANK不跳)。本题只取第一名,二者等价;若像 分数排名 那样需要完整名次,就必须想清楚要哪一种。- 另一类等价写法用
HAVING COUNT(*) = (SELECT MAX(cnt) FROM …),靠子查询取最大计数——可读但重复聚合一次,不如窗口函数干净。
📝 总结
「每组计数的 Top-1」模板:
- 只需第一名 →
GROUP BY 分组列+ORDER BY COUNT(*) DESC+LIMIT 1(可包一层 CTE 提升可读性); - 需处理并列 / 完整名次 → 子查询里
DENSE_RANK() OVER (ORDER BY COUNT(*) DESC),外层筛ranking = 1。
核心坑点:① 聚合函数不能嵌套(MAX(COUNT(*)) 非法);② LIMIT 1 在并列时结果不确定,仅适合作题目的「唯一」保证。
🔗 题集索引:LeetCode题集索引 · 算法地图:学习-数据结构与算法MOC
📎 同类题:从不订购的用户 · 分数排名 · 部门工资最高的员工 | 概念:SQL原理_02 · SQL原理_03
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






