如何返回满足聚合函数筛选条件的所有单行数据?
如何返回客户首次购买日期当天的所有订单
假设我有一个采购订单表,想要按单个客户分组,返回所有与该客户首次购买日期同一天的采购订单。我认为使用min(purchase_date)并按客户分组只能返回单行数据,无法满足需求,请问该如何实现?
示例如下,这段SQL仅会返回单行数据,但我需要返回所有属于首次购买日期的订单:
select c.name, min(o.purchase_date) from customers c join orders o on c.id = o.customer_id group by c.name
方法一:子查询关联法
先通过子查询计算每个客户的首次购买日期,再关联原订单表筛选出对应日期的所有订单:
select c.name, o.purchase_date, o.order_id, o.amount -- 按需选择需要的字段 from customers c join orders o on c.id = o.customer_id join ( select customer_id, min(purchase_date) as first_purchase_date from orders group by customer_id ) first_orders on o.customer_id = first_orders.customer_id and o.purchase_date = first_orders.first_purchase_date
方法二:窗口函数法(推荐,适用于MySQL 8+、PostgreSQL、SQL Server等)
利用RANK()窗口函数按客户分组、订单日期排序,筛选出首次购买日期对应的所有订单(若客户同一天有多笔订单,RANK()会全部保留):
select name, purchase_date, order_id, amount from ( select c.name, o.purchase_date, o.order_id, o.amount, rank() over (partition by o.customer_id order by o.purchase_date) as date_rank from customers c join orders o on c.id = o.customer_id ) ranked_orders where date_rank = 1
如果使用ROW_NUMBER()替代RANK(),仅会返回首次日期的其中一笔订单(排序规则由数据库决定),因此RANK()更贴合需求。
方法三:关联子查询法(简洁但性能一般)
在WHERE子句中直接判断当前订单日期是否等于该客户的首次购买日期:
select c.name, o.purchase_date, o.order_id, o.amount from customers c join orders o on c.id = o.customer_id where o.purchase_date = ( select min(purchase_date) from orders where customer_id = o.customer_id )
这种写法代码简洁,但在数据量较大时,子查询会逐行执行,性能不如前两种方法。
内容的提问来源于stack exchange,提问作者Ian Vaughn
相关产品推荐
相关产品推荐

