You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写MySQL查询实现多年度月度用水量对比报表?

年度月度用水量对比查询方案

嗨Ruediger,针对你想要生成各年度月度用水量对比视图的需求,这里有两种实用的实现思路,你可以根据自己的数据库环境来选择:

方法一:使用条件聚合(推荐,适合固定年份的场景)

这种方法通过CASE WHEN语句在聚合时筛选对应年份的数据,直接将行数据转为列,写法简洁高效:

SELECT 
    MONTHNAME(TIMESTAMP) AS Month,
    -- 提取2018年对应月份的用水量,空值用0填充避免显示NULL
    IFNULL(MAX(CASE WHEN YEAR(TIMESTAMP) = 2018 THEN VALUE END), 0) AS '2018',
    -- 提取2019年对应月份的用水量
    IFNULL(MAX(CASE WHEN YEAR(TIMESTAMP) = 2019 THEN VALUE END), 0) AS '2019'
FROM fhem.history
WHERE 
    DEVICE LIKE 'Wasserverbrauch' 
    AND READING LIKE 'statStateMonthLast'
    AND YEAR(TIMESTAMP) IN (2018, 2019) -- 只筛选需要的年份,提升查询效率
GROUP BY MONTH(TIMESTAMP), MONTHNAME(TIMESTAMP) -- 按月份数字+名称分组,避免多语言环境下的名称差异
ORDER BY MONTH(TIMESTAMP); -- 按月份顺序排序,保证结果从1月到12月展示

小提示:

如果你的数据库是多语言环境,用MONTH(TIMESTAMP)分组比仅用MONTHNAME更可靠——不同语言的月份名称会有差异(比如德语的1月是Januar而非Jan),按月份数字分组能确保同月份的数据被正确聚合。

方法二:使用自连接(适合需要动态扩展年份的场景)

如果后续可能要添加更多年份,自连接的方式可以通过多次关联来扩展,不过写法会稍繁琐一些:

SELECT 
    a.Month,
    a.`2018`,
    IFNULL(b.`2019`, 0) AS '2019' -- 用0替代NULL,保证数值统一
FROM (
    -- 查询2018年的数据
    SELECT 
        MONTHNAME(TIMESTAMP) AS Month,
        VALUE AS '2018'
    FROM fhem.history
    WHERE 
        DEVICE LIKE 'Wasserverbrauch' 
        AND READING LIKE 'statStateMonthLast'
        AND YEAR(TIMESTAMP) = 2018
) a
LEFT JOIN (
    -- 查询2019年的数据
    SELECT 
        MONTHNAME(TIMESTAMP) AS Month,
        VALUE AS '2019'
    FROM fhem.history
    WHERE 
        DEVICE LIKE 'Wasserverbrauch' 
        AND READING LIKE 'statStateMonthLast'
        AND YEAR(TIMESTAMP) = 2019
) b ON a.Month = b.Month
ORDER BY MONTH(a.Month); -- 按月份顺序排序

补充说明:

使用LEFT JOIN可以保证即使某一年某个月份没有数据,也会显示该月份(对应年份的数值会被IFNULL处理为0),如果不需要替换NULL,直接写b.2019``即可。

内容的提问来源于stack exchange,提问作者Puetong0815

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:03:57