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

MySQL如何查询含当前月及未来5个月的17个月时间区间数据

构建MySQL 17个月时间区间查询(含当前月标识与图表对比数据)

需求

  • 获取17个月时间区间的数据:覆盖当前月往前11个月、当前月、未来5个月
  • 结果需包含字段:iCurrentMonth(1标识当前月,0为其他)、strCurrentDate(当前日期时间)
  • 查询结果用于Highcharts图表,支持区间内数据与当前月之前月份的对比

当前查询语句

SELECT
    MONTH(s_order_main.added_date)                  AS iMonth,
    s_order_main.channel                            AS strChannel,
    COUNT(DISTINCT s_order_styles.s_order_style_id) AS iOrderCount,
    SUM(DISTINCT s_order_styles.sales_price)        AS fTurnover
FROM
    s_order_main
INNER JOIN
    s_order_styles ON s_order_styles.s_order_main_id = s_order_main.id
WHERE
    s_order_main.channel
    && s_order_main.order_type = 'pre'
    && YEAR(s_order_main.added_date) = YEAR(CURDATE() - INTERVAL 17 MONTH)
GROUP BY
    MONTH(s_order_main.added_date);

现有结果表

iMonthstrChanneliOrderCountfTurnover
1normal223433048.66
2normal663866711.96
3normal426630742.70
4normal171766.10
5normal90926.55
6normal125412334.04
7normal9212990.35
8normal946946407.63
9normal583731623.17
10normal70305.03
11normal3232726.99
12normal3706693.94

期望结果表

iMonthstrChanneliOrderCountfTurnoveriCurrentMonthstrCurrentDate
12normal223433048.6602021-12-22 13:54:09
1normal223433048.6602022-01-22 13:54:09
2normal663866711.9602022-02-22 13:54:09
3normal426630742.7002022-03-22 13:54:09
4normal171766.1002022-04-22 13:54:09
5normal90926.5502022-05-22 13:54:09
6normal125412334.0402022-06-22 13:54:09
7normal9212990.3502022-07-22 13:54:09
8normal946946407.6302022-08-22 13:54:09
9normal583731623.1702022-09-22 13:54:09
10normal70305.0302022-10-22 13:54:09
11normal3232726.9912022-10-22 13:54:09
12normal3706693.9402022-12-22 13:54:09
1b2b3706693.9402023-01-22 13:54:09
2normal3706693.9402023-02-22 13:54:09
3b2b3706693.9402023-03-22 13:54:09
4normal3706693.9402023-04-22 13:54:09

优化后的查询语句

WITH RECURSIVE month_sequence AS (
    -- 起始月份:当前月往前11个月
    SELECT 
        DATE_FORMAT(CURDATE() - INTERVAL 11 MONTH, '%Y-%m-01') AS month_start,
        MONTH(CURDATE() - INTERVAL 11 MONTH) AS iMonth,
        YEAR(CURDATE() - INTERVAL 11 MONTH) AS iYear
    UNION ALL
    -- 递归生成后续16个月(总共17个月)
    SELECT 
        DATE_ADD(month_start, INTERVAL 1 MONTH) AS month_start,
        MONTH(DATE_ADD(month_start, INTERVAL 1 MONTH)) AS iMonth,
        YEAR(DATE_ADD(month_start, INTERVAL 1 MONTH)) AS iYear
    FROM month_sequence
    WHERE month_start <= LAST_DAY(CURDATE() + INTERVAL 5 MONTH)
),
-- 获取所有渠道列表
channel_list AS (
    SELECT DISTINCT channel AS strChannel FROM s_order_main WHERE channel IS NOT NULL
)
SELECT
    ms.iMonth,
    cl.strChannel,
    COALESCE(COUNT(DISTINCT sos.s_order_style_id), 0) AS iOrderCount,
    COALESCE(SUM(DISTINCT sos.sales_price), 0) AS fTurnover,
    -- 当前月标识:1表示当前年月匹配,0否则
    CASE WHEN DATE_FORMAT(ms.month_start, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') THEN 1 ELSE 0 END AS iCurrentMonth,
    -- 当前日期时间
    CURRENT_TIMESTAMP() AS strCurrentDate
FROM month_sequence ms
CROSS JOIN channel_list cl
-- 左连接订单数据,确保所有月份和渠道都有记录
LEFT JOIN s_order_main som 
    ON DATE_FORMAT(som.added_date, '%Y-%m') = DATE_FORMAT(ms.month_start, '%Y-%m')
    AND som.channel = cl.strChannel
    AND som.order_type = 'pre'
LEFT JOIN s_order_styles sos 
    ON sos.s_order_main_id = som.id
GROUP BY ms.iYear, ms.iMonth, cl.strChannel
ORDER BY ms.month_start, cl.strChannel;

关键优化说明

  1. 完整月份序列:用递归CTE生成17个月的连续日期范围,避免缺失未来月份或历史月份
  2. 多渠道覆盖:通过channel_list获取所有存在的渠道,确保每个渠道在每个月份都有记录
  3. 当前月标识:通过年月匹配准确判断当前月,避免仅用月份判断导致跨年错误
  4. 空值处理:用COALESCE将无数据的月份订单数和营业额设为0,符合图表展示需求
  5. 时间区间修正:原查询仅筛选单一年份,优化后覆盖正确的17个月范围

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:31:06