select customer_id, min(order_date) as first_date, customer_pref_delivery_date
from Delivery
group by customer_id
ORDER BY customer_id;

这是输入表Delivery

delivery_id customer_id order_date customer_pref_delivery_date
1 1 2019-08-01 2019-08-02
2 2 2019-08-02 2019-08-02
3 1 2019-08-11 2019-08-12
4 3 2019-08-24 2019-08-24
5 3 2019-08-21 2019-08-22
6 2 2019-08-11 2019-08-13
7 4 2019-08-09 2019-08-09

这是我的结果:

customer_id first_date customer_pref_delivery_date
1 2019-08-01 2019-08-02
2 2019-08-02 2019-08-02
3 2019-08-21 2019-08-24
4 2019-08-09 2019-08-09

这是预期的结果:

customer_id first_date customer_pref_delivery_date
1 2019-08-01 2019-08-02
2 2019-08-02 2019-08-02
3 2019-08-21 2019-08-22
4 2019-08-09 2019-08-09

您能帮我,为什么当order_date为2019-08-24时,客户3的customer_pref_delivery_date来自不同行?甚至我将其设置为MIN(order_date),我认为SQL将从同一行返回customer_pref_delivery_date。为什么不是这种情况以及如何解决此问题?

太感谢了!

往上看!太感谢了!

分析解答

问题是您要选择customer_pref_delivery_date列,但没有将其添加到GROUP BY子句中或将其放入聚合功能中。

这通常是无效的SQL语法。因此,这是"luck"的纯粹,该查询完全是执行的,不会产生错误消息。

获得所需结果的一个选项是使用CTE,该CTE为每个customer_id获取MIN(order_date),然后使用外部查询添加其他列:

WITH minData AS
  (SELECT customer_id, MIN(order_date) AS order_date
   FROM Delivery
   GROUP BY customer_id)
SELECT
  customer_id, 
  order_date AS first_date, 
  customer_pref_delivery_date 
FROM Delivery
WHERE
  (customer_id, order_date) IN 
    (SELECT customer_id, order_date FROM minData)
ORDER BY customer_id;

IN子句(您也可以使用INNER JOIN)确保仅获取相关行。

这里是基于您的数据的样品小提琴

为了防止以后的问题:如上所述,您应该注意使用GROUP BY时使用有效的语法。您要选择的那些列必须添加到GROUP BY子句中,或在MINMAXAVG等的聚合功能中使用。

否则,当不遵守这些规则时,不正确的结果将是您将遇到的最佳情况。通常,您会收到这样的错误消息:

Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'Delivery.customer_pref_delivery_date' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

不幸的是,MySQL有一些丑陋的黑客,可以使用错误的语法。如果您观察到这种情况,我强烈建议将其禁用。因此,您将避免您的问题中解释的问题。

以下命令应停止此模式并启用"standard"模式:

SET sql_mode = 'ONLY_FULL_GROUP_BY';

这样做,您不会想知道意外结果,但会了解GROUP BY语法的问题,因此解决问题要容易得多。