如何在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
相关产品推荐
相关产品推荐

