如何使用SQL展示指定起止日期范围内的所有月份?
生成起止日期之间的所有月份(SQL实现)
根据你的需求,以下是不同SQL数据库的实现方案,生成起止日期之间的所有月份并格式化为Mon-YYYY样式:
通用递归CTE方案(支持MySQL 8.0+、PostgreSQL、SQL Server等)
递归CTE是最灵活的方式,适用于大多数现代数据库:
MySQL 8.0+ / MariaDB 10.2+
WITH RECURSIVE month_range AS ( -- 初始化:获取起始日期所在月份的第一天 SELECT DATE_FORMAT(start_date, '%Y-%m-01') AS month_start FROM ( -- 替换为你的起止日期,格式为DD-MM-YYYY SELECT STR_TO_DATE('12-09-2022', '%d-%m-%Y') AS start_date, STR_TO_DATE('05-05-2023', '%d-%m-%Y') AS end_date ) AS dates UNION ALL -- 递归:每月加1个月 SELECT DATE_ADD(month_start, INTERVAL 1 MONTH) FROM month_range -- 终止条件:不超过结束日期所在月份的第一天 WHERE month_start <= (SELECT DATE_FORMAT(end_date, '%Y-%m-01') FROM dates) ) -- 格式化输出为缩写月份+年份 SELECT DATE_FORMAT(month_start, '%b-%Y') AS month_year FROM month_range;
PostgreSQL
WITH RECURSIVE month_range AS ( -- 初始化:获取起始日期所在月份的起始时间 SELECT date_trunc('month', start_date)::DATE AS month_start FROM ( -- 替换为你的起止日期,格式为DD-MM-YYYY SELECT TO_DATE('12-09-2022', 'DD-MM-YYYY') AS start_date, TO_DATE('05-05-2023', 'DD-MM-YYYY') AS end_date ) AS dates UNION ALL -- 递归:每月加1个月 SELECT (month_start + INTERVAL '1 month')::DATE FROM month_range -- 终止条件:不超过结束日期所在月份的起始时间 WHERE month_start <= date_trunc('month', (SELECT end_date FROM dates)) ) -- 格式化输出为缩写月份+年份 SELECT TO_CHAR(month_start, 'Mon-YYYY') AS month_year FROM month_range;
SQL Server
WITH month_range AS ( -- 初始化:获取起始日期所在月份的第一天 SELECT DATEFROMPARTS(YEAR(start_date), MONTH(start_date), 1) AS month_start FROM ( -- 替换为你的起止日期,格式为DD-MM-YYYY(105对应该格式) SELECT CONVERT(DATE, '12-09-2022', 105) AS start_date, CONVERT(DATE, '05-05-2023', 105) AS end_date ) AS dates UNION ALL -- 递归:每月加1个月 SELECT DATEADD(MONTH, 1, month_start) FROM month_range -- 终止条件:不超过结束日期所在月份的第一天 WHERE month_start <= DATEFROMPARTS(YEAR((SELECT end_date FROM dates)), MONTH((SELECT end_date FROM dates)), 1) ) -- 格式化输出为缩写月份+年份 SELECT FORMAT(month_start, 'MMM-yyyy') AS month_year FROM month_range;
旧版MySQL(无CTE支持)方案
如果使用MySQL 5.x等不支持递归CTE的版本,可以用数字序列表生成:
SELECT DATE_FORMAT( DATE_ADD(STR_TO_DATE('12-09-2022', '%d-%m-%Y'), INTERVAL n MONTH), '%b-%Y' ) AS month_year FROM ( -- 生成足够多的数字(覆盖最大月份差即可) SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 ) AS numbers -- 过滤不超过结束日期的月份 WHERE DATE_ADD(STR_TO_DATE('12-09-2022', '%d-%m-%Y'), INTERVAL n MONTH) <= STR_TO_DATE('05-05-2023', '%d-%m-%Y');
以上方案执行后,都会输出你期望的结果:
Sep-2022 Oct-2022 Nov-2022 Dec-2022 Jan-2023 Feb-2023 Mar-2023 Apr-2023 May-2023
内容的提问来源于stack exchange,提问作者rish__ab__
相关产品推荐
相关产品推荐

