考虑下表。
+----+------+--------+-------------+---------------------+
| id | user | amount | description | paid_on |
+----+------+--------+-------------+---------------------+
| 1 | 1 | 200 | wire | 2017-09-01 15:45:52 |
| 2 | 2 | 200 | paypal | 2017-09-09 05:05:05 |
| 3 | 3 | 150 | cash | 2017-09-02 12:34:56 |
| 4 | 1 | 20 | wire | 2017-01-09 01:23:45 |
+----+------+--------+-------------+---------------------+
我正在尝试获取每个用户的总付款,以及同一用户的最后付款日期。为此,我正在使用
SELECT
user,
ROUND(SUM(amount),2) AS amount,
date_format(paid_on, '%d.%m.%Y.') AS paid_on
FROM
(
SELECT
user,
amount,
paid_on
FROM payments
WHERE paid_on BETWEEN '2017-09-01 00:00:00' AND '2017-09-30 23:59:59'
ORDER BY paid_on DESC
) tmppayments
GROUP BY user
它按照我的预期工作,因为它返回了我的想法。但是,使用子查询似乎有些矫枉过正。是否可以使用简单的 (r) 查询来完成此操作,而无需诉诸任何子查询?
最佳答案
您根本不需要子查询。并且,您还可以简化日期逻辑:
SELECT p.user, SUM(p.amount) as total_amount, MAX(p.paid_on) as max_paid_on
FROM payments p
WHERE p.paid_on >= '2017-09-01' AND p.paid_on <'2017-10-01'
GROUP BY user
ORDER BY max_paid_on DESC;
注意事项:
- 您可以根据需要格式化
max_paid_on
。与其他任何格式相比,我更喜欢 ISO 标准格式 YYYY-MM-DD。 - 我不建议将
BETWEEN
与日期或日期时间列一起使用。 Here是一篇很好的博客文章,解释了原因(虽然它适用于 SQL Server,但它确实适用于所有数据库)。 - 您的查询有逻辑错误。在外层
select
中,paid_on
没有被聚合,也不在group by
中。这在几乎任何其他数据库中都是错误的。 - 关于子查询,你是对的。 MySQL 实现了子查询,这对于不需要子查询的查询来说是不必要的开销。
关于mysql - 从一列中使用 SUM 和 GROUP BY 为另一列选择 MAX,没有子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46543447/