mysql - 从一列中使用 SUM 和 GROUP BY 为另一列选择 MAX,没有子查询

标签 mysql sql

考虑下表。

+----+------+--------+-------------+---------------------+
| 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/

相关文章:

MySQL:连接表并根据另一列上的聚合函数从一行返回一列

java - 想要为我的 java mysql 项目制作安装文件

php - 从数据库 mysql 和 PHP 应用折扣

php - Symfony/Propel - 从数据库中检索旧日期

mysql - 查找具有相同关键字的所有产品

php - 为什么我的 SQL 语句在我指定日期选择器的输出日期之前将数据显示到表中

MySQL 2 个表 UNION

MYSQL 查询/子查询合并

sql - 如何在大型数据库的 sqlite 中为数据表行分配索引?

mysql - 如果 SELECT 中存在 NULL 列,则删除不同的行