SQL如何按客户分组查询每个客户最早的3条订单记录
按客户分组取最早3条订单记录的实现方案
你原有写法的问题在于:LIMIT是对整个查询的结果集做行数截断,无法实现分组维度的Top N截取,要实现每个客户单独返回最早3条时间升序记录的需求,最通用高效的方案是使用窗口函数实现分组排名。
支持窗口函数的数据库写法(MySQL 8.0+、PostgreSQL、SQL Server、BigQuery等)
SELECT customer_id, timestamp FROM ( SELECT customer_id, timestamp, ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY timestamp ASC ) AS order_rank FROM customer_orders -- 若存在同客户同时间戳的重复记录需要去重,可替换为 SELECT DISTINCT customer_id, timestamp ) t WHERE order_rank <= 3 ORDER BY customer_id ASC, timestamp ASC;
语法说明
PARTITION BY customer_id指定排名的分组维度为客户ID,不同客户的排名独立计算ORDER BY timestamp ASC指定组内的排序规则为时间从早到晚,生成的排名从1开始依次递增- 外层筛选
order_rank <=3即可拿到每个客户下时间最早的3条记录 - 若业务场景下需要保留同时间戳的并列记录,可将
ROW_NUMBER()替换为RANK(),避免同时间订单被意外截断
兼容不支持窗口函数的老版本(MySQL 5.x等)写法
如果你的数据库版本不支持窗口函数,可以通过关联子查询实现相同逻辑:
SELECT DISTINCT co1.customer_id, co1.timestamp FROM customer_orders co1 WHERE ( SELECT COUNT(DISTINCT co2.timestamp) FROM customer_orders co2 WHERE co2.customer_id = co1.customer_id AND co2.timestamp <= co1.timestamp ) <= 3 ORDER BY co1.customer_id ASC, co1.timestamp ASC;
内容的提问来源于stack exchange,提问作者Dizz
相关产品推荐
相关产品推荐

