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

如何在Hive中获取指定日期至当前月份的所有不同月份值

嘿,这个需求我之前帮人解决过好几次,刚好适合用来做月度用户统计!下面给你几个不同技术栈的实现方案,你按需选:

Python 实现

用 datetime 配合 dateutil.relativedelta 可以轻松生成月份序列,代码简洁易懂:

from datetime import datetime
from dateutil.relativedelta import relativedelta

# 起始日期和当前日期
start_date = datetime.strptime("2011-11-05", "%Y-%m-%d")
current_date = datetime.now()

months = []
# 从起始月的第一天开始遍历
current_month = start_date.replace(day=1)
while current_month <= current_date.replace(day=1):
    # 格式化为YYYY-MM的字符串
    months.append(current_month.strftime("%Y-%m"))
    # 逐月递增
    current_month += relativedelta(months=1)

# 转换成空格分隔的最终格式
result = " ".join(months)
print(result)

MySQL 实现

如果你的用户数据存在MySQL里,直接用递归CTE生成月份序列,还能顺便完成统计:

生成月份字符串集合

WITH RECURSIVE month_sequence AS (
    -- 起始月的第一天
    SELECT DATE_FORMAT('2011-11-05', '%Y-%m-01') AS month_date
    UNION ALL
    -- 逐月递增
    SELECT DATE_ADD(month_date, INTERVAL 1 MONTH)
    FROM month_sequence
    -- 终止条件:不超过当前月第一天
    WHERE month_date < DATE_FORMAT(NOW(), '%Y-%m-01')
)
-- 拼接成空格分隔的字符串
SELECT GROUP_CONCAT(DATE_FORMAT(month_date, '%Y-%m') SEPARATOR ' ') AS month_list
FROM month_sequence;

直接统计月度活跃/非活跃用户

如果要一步到位完成统计,不用单独生成月份集合,可以这么写:

WITH RECURSIVE month_sequence AS (
    SELECT DATE_FORMAT('2011-11-05', '%Y-%m-01') AS month_date
    UNION ALL
    SELECT DATE_ADD(month_date, INTERVAL 1 MONTH)
    FROM month_sequence
    WHERE month_date < DATE_FORMAT(NOW(), '%Y-%m-01')
)
SELECT 
    DATE_FORMAT(ms.month_date, '%Y-%m') AS month,
    COUNT(DISTINCT ua.user_id) AS active_users,
    -- 总用户数减去活跃用户数就是非活跃用户数
    (SELECT COUNT(user_id) FROM users) - COUNT(DISTINCT ua.user_id) AS inactive_users
FROM month_sequence ms
-- 关联用户活动表,匹配当月有活动的用户
LEFT JOIN user_activity ua ON DATE_FORMAT(ua.activity_date, '%Y-%m-01') = ms.month_date
GROUP BY ms.month_date
ORDER BY ms.month_date;

JavaScript 实现

不管是前端还是Node.js环境,都可以用原生Date对象实现:

function generateMonthRange(startDateStr, endDate = new Date()) {
    const startDate = new Date(startDateStr);
    // 把起始日期设为当月第一天,避免日期差异影响
    startDate.setDate(1);
    // 终止日期设为当前月第一天
    const endMonth = new Date(endDate.getFullYear(), endDate.getMonth(), 1);
    
    const months = [];
    let currentMonth = new Date(startDate);
    
    while (currentMonth <= endMonth) {
        const year = currentMonth.getFullYear();
        // 月份是0-11,所以要加1,并且补前导零
        const month = String(currentMonth.getMonth() + 1).padStart(2, '0');
        months.push(`${year}-${month}`);
        // 逐月递增
        currentMonth.setMonth(currentMonth.getMonth() + 1);
    }
    
    // 转换成空格分隔的字符串
    return months.join(' ');
}

// 使用示例
const result = generateMonthRange('2011-11-05');
console.log(result);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:52:51