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

SQL如何实现按每个月份统计对应ID过去6个月的出现次数

实现方案

完全可以用自连接实现,这也是对SQL初学者来说逻辑最直观的写法,另外也提供性能更好的窗口函数写法,你可以根据自己使用的数据库选择。

首先统一前提:假设你的表名为target_table,包含两个核心字段:

  • id:需要统计的主体ID
  • stat_month:月份字段,为日期类型(建议统一存每个月第一天,例如2023-01-01代表2023年1月,不建议用字符串/数字格式存月份,会大幅增加日期计算的出错概率)
    默认统计规则:对每条记录,取包含当月在内的近6个自然月范围内,同ID的记录出现次数,和你给出的示例结果逻辑一致。

方法1:自连接实现

核心逻辑是把同一张表取两个别名使用:主表返回所有原始记录,连接后的副表用来匹配符合时间范围的历史记录,最后分组计数即可。

SELECT
  t1.id,
  t1.stat_month,
  COUNT(t2.stat_month) AS cnt_6month
FROM target_table t1
LEFT JOIN target_table t2
  ON t1.id = t2.id
  -- 时间范围:当前记录月份往前推5个月到当月,总共6个自然月
  AND t2.stat_month >= DATE_SUB(t1.stat_month, INTERVAL 5 MONTH)
  AND t2.stat_month <= t1.stat_month
GROUP BY t1.id, t1.stat_month
ORDER BY t1.id, t1.stat_month;

不同数据库的日期计算函数需要做对应替换:

  • PostgreSQL:把DATE_SUB部分换成t2.stat_month >= t1.stat_month - INTERVAL '5 months'
  • SQL Server:把DATE_SUB部分换成t2.stat_month >= DATEADD(month, -5, t1.stat_month)
    如果你的表存在同一个ID同一个月多条记录的情况,这个写法也能正常统计,不需要额外去重。

方法2:窗口函数实现(数据量大时优先选)

如果你用的数据库支持窗口函数(MySQL8.0及以上、PostgreSQL、SQL Server、主流大数据组件都支持),可以直接用带滑动窗口的聚合写法,不需要做表连接,性能比自连接高很多:

SELECT
  id,
  stat_month,
  COUNT(*) OVER (
    PARTITION BY id
    ORDER BY stat_month
    ROWS BETWEEN 5 PRECEDING AND CURRENT ROW
  ) AS cnt_6month
FROM target_table
ORDER BY id, stat_month;

注意:这个写法有适用前提:每个ID对应的月份是连续无缺失、且每个自然月最多只有1条记录。如果存在缺月、或者单月多条记录的情况,还是用自连接的日期范围匹配逻辑更稳妥,避免统计窗口偏移。


注意事项

  • 先确认业务侧的时间范围规则:如果是精确回溯6个月的时间跨度(例如2023-06-15的记录统计2023-01-15之后的数据),只需要调整上面日期条件里的INTERVAL值为6个月,同时把上界改成小于当前记录日期即可。
  • 如果你的Month字段目前是字符串(例如'2023-06')或者数字(例如202306)格式,建议先转成原生日期类型再做计算,不然需要额外处理跨年、月份借位的逻辑,很容易出bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:19:19