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

如何在SQL中获取近两个月名称并替换查询中的M1、M2标签?

用实际月份名称替代M_1/M_2标识的SQL解决方案

嘿,这个问题太常见了——用M1、M2确实容易让同事搞混,换成带年份的实际月份名称(比如2024-05_Ratio)绝对能大幅提升可读性。下面我根据不同的SQL方言给你适配好的方案,你可以直接套用:

方案1:MySQL 实现动态月份别名

如果用MySQL,你可以先定义变量存储上月/上上月的格式化名称,再通过动态SQL生成带实际月份的列别名:

-- 定义月份标签变量,格式可按需调整(比如'%b %Y'会生成'May 2024')
SET @last_month = DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m');
SET @two_months_ago = DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 MONTH), '%Y-%m');

-- 构建动态SQL并执行
SET @sql = CONCAT(
    'SELECT 
        *,
        CONCAT(FORMAT((current_downloads/M_1)*100,2),''%'') AS `', @last_month, '_Ratio`,
        CONCAT(FORMAT((current_downloads/M_2)*100,2),''%'') AS `', @two_months_ago, '_Ratio`
    FROM (
        -- 这里替换成你原来的子查询逻辑,确保M_1是上月数据、M_2是上上月数据
        SELECT 
            COUNT(*) AS current_downloads,
            SUM(CASE WHEN download_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND download_date < CURDATE() THEN 1 ELSE 0 END) AS M_1,
            SUM(CASE WHEN download_date >= DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND download_date < DATE_SUB(CURDATE(), INTERVAL 1 MONTH) THEN 1 ELSE 0 END) AS M_2
        FROM downloads
        -- 你的过滤条件
    ) AS subquery;'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

方案2:PostgreSQL 实现动态月份别名

PostgreSQL可以用DO块执行动态SQL,或者用CTE先获取月份标签:

DO $$
DECLARE
    -- 定义月份标签,格式可调整为'Mon YYYY'生成'May 2024'
    last_month TEXT := TO_CHAR(CURRENT_DATE - INTERVAL '1 month', 'YYYY-MM');
    two_months_ago TEXT := TO_CHAR(CURRENT_DATE - INTERVAL '2 months', 'YYYY-MM');
    sql_query TEXT;
BEGIN
    sql_query := '
        SELECT 
            *,
            CONCAT(TO_CHAR((current_downloads/M_1)*100, ''FM999.99''),''%'') AS "' || last_month || '_Ratio",
            CONCAT(TO_CHAR((current_downloads/M_2)*100, ''FM999.99''),''%'') AS "' || two_months_ago || '_Ratio"
        FROM (
            -- 替换成你的子查询逻辑
            SELECT 
                COUNT(*) AS current_downloads,
                SUM(CASE WHEN download_date >= CURRENT_DATE - INTERVAL ''1 month'' AND download_date < CURRENT_DATE THEN 1 ELSE 0 END) AS M_1,
                SUM(CASE WHEN download_date >= CURRENT_DATE - INTERVAL ''2 months'' AND download_date < CURRENT_DATE - INTERVAL ''1 month'' THEN 1 ELSE 0 END) AS M_2
            FROM downloads
        ) AS subquery;
    ';
    EXECUTE sql_query;
END $$;

方案3:SQL Server 实现动态月份别名

SQL Server用sp_executesql来执行动态SQL,步骤类似:

DECLARE @last_month NVARCHAR(7) = FORMAT(DATEADD(MONTH, -1, GETDATE()), 'yyyy-MM');
DECLARE @two_months_ago NVARCHAR(7) = FORMAT(DATEADD(MONTH, -2, GETDATE()), 'yyyy-MM');
DECLARE @sql NVARCHAR(MAX);

SET @sql = N'
    SELECT 
        *,
        CONCAT(FORMAT((current_downloads/M_1)*100, ''N2''),''%'') AS [' + @last_month + '_Ratio],
        CONCAT(FORMAT((current_downloads/M_2)*100, ''N2''),''%'') AS [' + @two_months_ago + '_Ratio]
    FROM (
        -- 替换成你的子查询逻辑
        SELECT 
            COUNT(*) AS current_downloads,
            SUM(CASE WHEN download_date >= DATEADD(MONTH, -1, GETDATE()) AND download_date < GETDATE() THEN 1 ELSE 0 END) AS M_1,
            SUM(CASE WHEN download_date >= DATEADD(MONTH, -2, GETDATE()) AND download_date < DATEADD(MONTH, -1, GETDATE()) THEN 1 ELSE 0 END) AS M_2
        FROM downloads
    ) AS subquery;
';

EXEC sp_executesql @sql;

额外小贴士

  • 月份格式自定义:可以把%Y-%m换成其他格式,比如%b %Y(MySQL)、Mon YYYY(PostgreSQL)、MMM yyyy(SQL Server),生成更直观的May 2024_Ratio
  • 自然月统计:如果你的数据是按自然月(每月1号到月底)统计,要调整日期过滤逻辑,比如用DATE_FORMAT(download_date, '%Y-%m') = DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m')来确保统计的是完整自然月数据
  • 报表工具替代方案:如果是在Tableau、Power BI等工具里使用,也可以在工具层面把M_1、M_2字段映射成实际月份名称,SQL不用修改,灵活性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:09:01