You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在HAVING子句中使用MIN()查询客户最早订单日期遇异常的原因及解决

为什么GROUP BY + HAVING的写法无法返回每个用户的最早订单日期?

问题原因

你原SQL的核心问题出在GROUP BY的逻辑和非聚合列的处理上:

  • 当你用GROUP BY customer_id时,数据库会把同一个customer_id的行合并成一个分组。此时SELECT里的order_date属于非聚合、非分组键的列,在大多数严格的SQL模式(比如MySQL的ONLY_FULL_GROUP_BY开启时)会直接报错;如果模式宽松,数据库会随机从该分组的行里选一个order_date返回,这个值不一定是最小的那个。
  • 接着HAVING MIN(order_date) = order_date的判断,只有当随机选中的这个order_date刚好等于该分组的最小日期时,这条记录才会被保留。像你提到的customer_id=7,分组后随机返回的是'2019-07-22',而该分组的MIN(order_date)是'2019-07-08',条件不满足,所以这条记录就被过滤掉了。

简单说:GROUP BY后你拿到的order_date是随机的,不是全部分组内的日期,自然无法和最小日期匹配出所有符合条件的行。

可行的解决方法

方法1:你提到的子查询+WHERE IN

这种写法先通过子查询算出每个用户的最小订单日期,再用WHERE条件匹配原表中对应的行:

SELECT customer_id, order_date
FROM Delivery
WHERE (customer_id, order_date) IN (
    SELECT customer_id, MIN(order_date)
    FROM Delivery
    GROUP BY customer_id
)

方法2:窗口函数(更高效的写法)

用ROW_NUMBER()窗口函数给每个用户的订单按日期排序,标记出最早的那一行,再筛选出来:

SELECT customer_id, order_date
FROM (
    SELECT 
        customer_id, 
        order_date,
        ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY order_date ASC) AS rn
    FROM Delivery
) t
WHERE rn = 1

如果存在同一个用户同一天多个订单的情况,想保留所有的话,可以把ROW_NUMBER()换成RANK()或者DENSE_RANK()。

内容的提问来源于stack exchange,提问作者BenS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:52:42