MySQL查询年度/每月报告

时间:2019-12-30 09:48:31

标签: mysql sql date

您好,我有一个桌子,该桌子由我的家庭自动化设备填充。 我原则上只有一张表包含所有值。 一些条目是通过统计模块进行的。它计算每月的用水量。 现在,我想创建一个查询,以提供每年消耗量的详细视图。

赞:

|Month|2018|2019|  
|Jan..|7.3 |6.8|  
|Feb  |5.9 |7.8|....

查询一年:

SELECT
    monthname(TIMESTAMP) Monat,
    VALUE '2018'
FROM
    fhem.history acht
WHERE
    DEVICE LIKE 'Wasserverbrauch' 
    AND READING LIKE 'statStateMonthLast' 
    AND year(TIMESTAMP) = 2018

但是我如何才能加入2019年的价值观呢?有人可以指出我正确的方向吗?

谢谢,
鲁迪格(Ruediger)

3 个答案:

答案 0 :(得分:1)

您可以进行条件聚合:

SELECT
    MONTHNAME(timestamp) Monat,
    MAX(CASE WHEN timestamp >= '2018-01-01' AND timestamp < '2019-01-01' THEN value END) `2018`,
    MAX(CASE WHEN timestamp >= '2019-01-01' AND timestamp < '2020-01-01' THEN value END) `2019`
FROM fhem.history acht
WHERE
    device = 'Wasserverbrauch' 
    AND reading = 'statStateMonthLast' 
    AND timestamp >= '2018-01-01' 
    AND timestamp < '2020-01-01'
GROUP BY MONTHNAME(timestamp)

注意:

  • LIKE子句中的WHERE条件实际上等效于=,因为正确的操作数中没有通配符;我相应地更改了它们

  • 通常最好进行显式的日期时间范围比较,而不要使用日期函数(在您的情况下为year()),因为后者会阻止使用索引

  • 如果您每个月需要处理多个记录员(根据您现有的查询来看似乎不是这种情况),则应该使用另一个聚合函数来获得更明智的结果(sum()avg()

答案 1 :(得分:0)

您可以使用EXTRACT()函数从时间戳获取年/月,并使用条件表达式将其全部放入列中。
我认为带有月份数字和名称的表对于外部联接很有用。

SELECT 
  m.`month`, 
  SUM(IF(h.`year_no`=2019, h.`value`, 0)) AS `2019`, 
  SUM(IF(h.`year_no`=2020, h.`value`, 0)) AS `2020`
FROM `monthes` AS m
LEFT JOIN (
  SELECT 
    EXTRACT(YEAR FROM `timestamp`) AS `year_no`,
    EXTRACT(MONTH FROM `timestamp`) AS `month_no`,
    `value`
  FROM `history`
) AS h ON h.`month_no` = m.`id`
GROUP BY m.`id`

我使用了GROUP BY月份ID,因此结果将按月份编号而不是月份名称隐式排序。

https://www.db-fiddle.com/f/78LQtak6GwkDS8pzredroQ/0

为求勇敢,我在这里没有使用其他过滤器,但是如果需要它们,请将WHERE...添加到嵌套子查询的右侧FROM history下。

答案 2 :(得分:0)

这是GMB回答的变体。但是,如果您希望结果按时间顺序按月排列,则需要在查询中包括:

SELECT MONTHNAME(timestamp) as Monat,
       SUM(CASE WHEN YEAR(timestamp) = 2018 THEN value END) value_2018,
       SUM(CASE WHEN YEAR(timestamp) = 2019 THEN value END) as value_2019
FROM fhem.history acht
WHERE device = 'Wasserverbrauch' AND
      reading = 'statStateMonthLast' AND
      timestamp >= '2018-01-01' AND
      timestamp < '2020-01-01'
GROUP BY MONTHNAME(timestamp), MONTH(timestamp)
ORDER BY MONTH(timestamp);