【问题标题】:Mysql sum for last 12 months过去 12 个月的 Mysql 总和
【发布时间】:2014-08-12 23:20:09
【问题描述】:

我正在尝试创建一个查询以获取基于月份的最近 12 个月的记录以进行图表表示。经过大量阅读和观看此similar topic 之后,我创建了一个看似正确但缺少 0 钱月份的查询。例如,我在图表中看到月份 1/14、2/14、4/14 等等......缺少 3/14。

我的代码是这样的

SELECT *
FROM
    (SELECT DATE_FORMAT(now(), '%m/%y') AS Month
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 1 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 2 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 3 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 4 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 5 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 6 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 7 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 8 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 9 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 10 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 11 MONTH), '%m/%y')
    ) AS Months
LEFT JOIN
    (SELECT sum(expenses.price) AS ExpenseAmount,
            sum(payments.amount) AS PaymentsAmount,
            DATE_FORMAT(expenses.date_occurred,'%m/%y') AS Month,
            DATE_FORMAT(payments.date_occurred,'%m/%y') AS Montha
     FROM expenses,
          payments
     WHERE payments.user_id= 1
         AND payments.user_id=expenses.user_id
     GROUP BY MONTH(payments.date_occurred),
              YEAR(payments.date_occurred)
     ORDER BY payments.date_occurred ASC ) data ON Months.MONTH = data.Montha
ORDER BY data.Montha;

任何帮助都会很棒,因为这种查询对我来说太高级了:-)

【问题讨论】:

  • 单独运行时,内联视图的输出(您已别名为“数据”)是什么样的?除了缺少的月份之外,您得到的输出是否正确?
  • (示例)在图表的图片中,我应该得到 0 月 4/14。但是在结果查询中没有这样的东西,所以它被跳过了。查询正确,确实没有这个月的数据。但我想在那里有一个空值和月份。让我这样做@Brian DeMilia,我会把它发布给你
  • 布莱恩这是一个 var_dump() laravel.io/bin/5We82

标签: mysql sql


【解决方案1】:

由于查询看起来应该为每个月生成一行,您能否检查查询输出,而不是您的图表生成的内容?我怀疑你有一个 04/14 的条目,但值是 NULL 而不是 0。要纠正这个问题,你可以将查询更改为 start

SELECT Months.Month, 
    COALESCE(data.ExpenseAmount, 0) AS ExpenseAmount, 
    COALESCE(data.PaymentAmount, 0) AS PaymentAmount

COALESCE 会给你 0 而不是 NULL 没有匹配你的左连接的行。

但是,您的查询中还有其他问题。只有在同一个月有费用和付款时,您才会得到行 - 检查http://sqlfiddle.com/#!2/3f52a8/1,如果您从一个表中删除一些数据,您会看到问题。

这是一个可行的解决方案,它可以为您提供所有月份,将两个表中的数据相加,即使只有一个表存在。这通过将费用和付款作为单独的查询处理,然后将它们连接在一起来实现。

SELECT Months.Month, COALESCE(expensedata.ExpenseAmount, 0) AS ExpenseAmount, COALESCE(paymentdata.PaymentAmount, 0) AS PaymentAmount
FROM
    (SELECT DATE_FORMAT(now(), '%m/%y') AS Month
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 1 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 2 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 3 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 4 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 5 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 6 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 7 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 8 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 9 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 10 MONTH), '%m/%y')
     UNION SELECT DATE_FORMAT(DATE_SUB(now(), INTERVAL 11 MONTH), '%m/%y')
    ) AS Months

LEFT JOIN 
  (SELECT SUM(price) AS ExpenseAmount, DATE_FORMAT(date_occurred,'%m/%y') AS Month
   FROM expenses 
   WHERE user_id = 1
   GROUP BY MONTH(date_occurred), YEAR(date_occurred)) expensedata ON Months.Month = expensedata.Month

LEFT JOIN 
  (SELECT SUM(amount) AS PaymentAmount, DATE_FORMAT(date_occurred,'%m/%y') AS Month
   FROM payments
   WHERE user_id = 1
   GROUP BY MONTH(date_occurred), YEAR(date_occurred)) paymentdata ON Months.Month = paymentdata.Month

ORDER BY Months.Month;

显示此工作的 SQL Fiddle:http://sqlfiddle.com/#!2/3f52a8/5

【讨论】:

  • 我 var_dump() 输出没有你的修复。问题似乎是它实际上并没有为每个月创建一行laravel.io/bin/5We82
  • Richard 我不知道该把你的建议放在哪里。我应该得到一个 sum(),对吧?
  • 在这样的问题中,如果您提供所有信息,特别是以包含一些示例数据的 SQL Fiddle 链接的形式,人们会更容易帮助您。否则,我们必须猜测您要使用的内容!我有一个猜测,并更新了我的答案。
  • 天哪。出色的查询理查德,从中学到了很多,这正是我想做的,好猜!唯一的问题是 2013 年的结果已经结束。我怎样才能让他们成为第一名?
  • 最简单的选择是将您的年份重新格式化为 %y-%m,这将产生 2013-01 等,按字母顺序排序。如果您想以不同的方式设置月份的格式,则需要在您的月份查询中将实际年份和月份作为单独的值包含在内,这样您就可以在 order by 语句中使用它们。
【解决方案2】:

我认为你的问题是左连接。您的左联接中的 select 语句的结果不包含任何 0 钱的结果...看起来像您的

where payments.user_id = 1 

问题是……

在以下链接下,您可以找到所有类型连接的解释...http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/

希望对你有帮助

【讨论】:

  • 查询正确,确实没有这个月的数据。但我想在那里有一个空值和月份。
【解决方案3】:

ORDER BY data.Montha 替换为ORDER BY Months.MONTH

data.Montha 中没有“3/14”。

【讨论】:

  • 您的原始声明不会造成任何月份的缺失。一定有别的东西。您应该发布您的环境信息,例如 db 版本和 os 版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
  • 2021-02-11
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多