You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL查询近3个月数据返回异常,寻求技术排查方案

解决MySQL查询最近3个月数据的问题

先帮你捋捋当前查询的问题:你写的last_day(now()) + INTERVAL 1 day - INTERVAL 3 month这个条件,其实是在计算当前月的第一天往前推3个月的第一天(举个例子,如果现在是2024年5月,这个表达式算出来的是2024-03-01),所以只会筛选出3月1日及以后的数据。你的表只有1月和5月的数据,那1月的记录早于3月1日,自然会被过滤掉,最终只能返回5月的汇总结果。

下面根据不同的需求场景,给你对应的解决方案:

场景1:要查过去3个自然月(包含当前月)的数据,没数据的月份显示0

如果你希望拿到最近3个完整的自然月(比如当前5月,就要3、4、5月),哪怕某个月没有预约记录,也要显示该月的total为0,那可以用递归CTE生成月份序列,再和你的表做左连接:

-- 先生成最近3个月的起始日期序列
WITH RECURSIVE months AS (
    SELECT 
        DATE_FORMAT(CURDATE() - INTERVAL 2 MONTH, '%Y-%m-01') AS month_start
    UNION ALL
    SELECT 
        DATE_ADD(month_start, INTERVAL 1 MONTH)
    FROM months
    WHERE month_start < DATE_FORMAT(CURDATE(), '%Y-%m-01')
)
SELECT 
    MONTH(m.month_start) AS month,
    COALESCE(SUM(a.service_price), 0) AS total
FROM months m
LEFT JOIN appointments a 
    ON a.user_id = 1 
    AND a.service_date_time >= m.month_start
    AND a.service_date_time < DATE_ADD(m.month_start, INTERVAL 1 MONTH)
GROUP BY YEAR(m.month_start), MONTH(m.month_start)
ORDER BY m.month_start;

这个查询会自动生成最近3个月的每个月第一天,然后左连接预约表统计金额,没有数据的月份用COALESCE把NULL转换成0。

场景2:要查过去90天(滚动式的3个月)的数据

如果你的“最近3个月”是指从今天往前推90天的滚动时间段(不是严格的自然月),那条件可以简化成这样:

SELECT 
    MONTH(service_date_time) AS month,
    SUM(service_price) AS total
FROM appointments 
WHERE 
    user_id = 1 
    AND service_date_time >= CURDATE() - INTERVAL 3 MONTH
GROUP BY YEAR(service_date_time), MONTH(service_date_time)
ORDER BY YEAR(service_date_time), MONTH(service_date_time);

比如今天是2024-05-20,这个条件会筛选出2024-02-20到2024-05-20之间的所有记录,然后按月份汇总。

场景3:要查最近3个有数据的月份(不管时间跨度)

如果你的需求是找出该用户在表中最近的3个有预约记录的月份(比如你的表有1月、5月的数据,当前是5月,那就是5月;如果还有4月的数据,就是5、4、1月这样按时间倒序的前3个),可以用下面的查询:

SELECT 
    MONTH(service_date_time) AS month,
    SUM(service_price) AS total
FROM appointments 
WHERE 
    user_id = 1 
    AND CONCAT(YEAR(service_date_time), '-', MONTH(service_date_time)) IN (
        SELECT DISTINCT CONCAT(YEAR(service_date_time), '-', MONTH(service_date_time))
        FROM appointments
        WHERE user_id = 1
        ORDER BY service_date_time DESC
        LIMIT 3
    )
GROUP BY YEAR(service_date_time), MONTH(service_date_time)
ORDER BY YEAR(service_date_time) DESC, MONTH(service_date_time) DESC;

子查询会先找出该用户最近3个有数据的月份,外层查询再统计这些月份的总金额。

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

火山引擎 最新活动