如何通过SQL查询获取客户最新订单记录TOP3?
修正SQL查询以获取每个客户最新订单的TOP3记录
你的原查询存在两个核心问题:
- GROUP BY子句不符合标准SQL规范:仅按
csm.id分组,但未将csm.name纳入GROUP BY。虽然部分数据库(如关闭ONLY_FULL_GROUP_BY的MySQL)允许这种写法,但可能返回不确定的name值,在严格SQL模式下会直接报错。 - 逻辑排序偏差:你期望的结果中
111(Karen E.)的订单日期2023-02-07是所有客户里最新的,原查询按ord_created_at降序排序的话,该记录应排在第一位,实际结果不符合预期大概率和分组逻辑或数据库非标准行为有关。
方案一:子查询分组获取最新日期后关联
先通过子查询计算每个客户的最新订单日期,再关联客户表获取名称,最后取TOP3:
SELECT TOP 3 c.id AS id_customer, c.name, latest.max_created_at AS ord_created_at FROM customers c INNER JOIN ( SELECT fk_customer, MAX(created_at) AS max_created_at FROM orders GROUP BY fk_customer ) latest ON c.id = latest.fk_customer ORDER BY latest.max_created_at DESC;
方案二:使用窗口函数(推荐,扩展性更强)
如果后续需要展示订单其他字段(如订单ID),窗口函数写法更灵活。通过ROW_NUMBER()为每个客户的订单按日期降序编号,取编号为1的最新订单,再排序取TOP3:
SELECT TOP 3 id_customer, name, ord_created_at FROM ( SELECT c.id AS id_customer, c.name, o.created_at AS ord_created_at, -- 按客户分组,订单日期降序编号 ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY o.created_at DESC) AS rn FROM customers c INNER JOIN orders o ON c.id = o.fk_customer ) ranked_orders WHERE rn = 1 -- 仅保留每个客户的最新订单 ORDER BY ord_created_at DESC;
正确结果说明
上述两种查询都会返回按订单日期降序排列的TOP3记录,正确结果应为:
| id_customer | name | ord_created_at |
|---|---|---|
| 111 | Karen E. | 2023-02-07 |
| 101 | Lucas D. | 2023-01-15 |
| 112 | Lucas F. | 2022-12-20 |
你给出的期望结果中101排在第一位是日期顺序的笔误,实际2023-02-07比2023-01-15更新。
内容的提问来源于stack exchange,提问作者Gabriel Vieira Lima
相关产品推荐
相关产品推荐

