使用LEAD函数获取下一日期,构建近6个月读数日期注册量统计查询
嘿,我来帮你搞定这个统计需求!根据你给出的输出格式,我假设你使用的是关系型数据库(比如PostgreSQL或MySQL),下面是针对性的SQL查询方案:
解决方案
核心思路分为三步:
- 生成26到31天的固定日期列表,确保哪怕某天没有注册记录也能显示0;
- 筛选出近6个月的注册数据,按地区(LOCALE)、月份(COMPETENCE)、读数日期(Reading_date)分组统计数量;
- 将固定日期列表和统计结果左连接,补全缺失日期的0值。
假设你的业务表名为 inscriptions,核心字段包括:
locale: 地区(如CEARA)reading_date: 读数日期(日期类型,如'2024-01-26')id: 注册记录唯一标识(用于统计数量)
PostgreSQL 版本查询语句
WITH date_range AS ( -- 生成26到31的天数序列 SELECT generate_series(26, 31) AS day ), recent_months AS ( -- 获取近6个月的月份标识(格式如JAN18) SELECT DISTINCT TO_CHAR(reading_date, 'MONYY') AS competence, locale FROM inscriptions WHERE reading_date >= CURRENT_DATE - INTERVAL '6 months' ) SELECT rm.locale AS LOCALE, rm.competence AS COMPETENCE, dr.day AS "Reading_date(DAYS)", COALESCE(COUNT(i.id), 0) AS "INSCRIPTION (Quantity)" FROM recent_months rm CROSS JOIN date_range dr LEFT JOIN inscriptions i ON rm.locale = i.locale AND TO_CHAR(i.reading_date, 'MONYY') = rm.competence AND EXTRACT(DAY FROM i.reading_date) = dr.day AND i.reading_date >= CURRENT_DATE - INTERVAL '6 months' GROUP BY rm.locale, rm.competence, dr.day ORDER BY rm.locale, rm.competence, dr.day;
MySQL 版本查询语句
WITH RECURSIVE date_range AS ( -- 生成26到31的天数序列 SELECT 26 AS day UNION ALL SELECT day + 1 FROM date_range WHERE day < 31 ), recent_months AS ( -- 获取近6个月的月份标识(格式如JAN18) SELECT DISTINCT DATE_FORMAT(reading_date, '%b%y') AS competence, locale FROM inscriptions WHERE reading_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) ) SELECT rm.locale AS LOCALE, rm.competence AS COMPETENCE, dr.day AS `Reading_date(DAYS)`, COALESCE(COUNT(i.id), 0) AS `INSCRIPTION (Quantity)` FROM recent_months rm CROSS JOIN date_range dr LEFT JOIN inscriptions i ON rm.locale = i.locale AND DATE_FORMAT(i.reading_date, '%b%y') = rm.competence AND DAY(i.reading_date) = dr.day AND i.reading_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) GROUP BY rm.locale, rm.competence, dr.day ORDER BY rm.locale, rm.competence, dr.day;
关键细节说明:
date_rangeCTE:生成26到31的天数,确保每个天数都出现在结果中,哪怕没有对应注册记录;recent_monthsCTE:提取近6个月内所有出现过的地区和月份组合,避免出现不存在的地区-月份条目;COALESCE函数:把NULL(没有注册记录的日期)转换成0,完全匹配你示例中的格式;- 月份格式转换:用
TO_CHAR(PostgreSQL)或DATE_FORMAT(MySQL)把日期转换成MONYY/%b%y格式,对应你要的JAN18样式; - 排序规则:最后按地区、月份、天数排序,让结果顺序和你示例一致。
如果你的业务表结构或字段名和假设的不一样,只需要调整对应的表名、字段名即可~
内容的提问来源于stack exchange,提问作者Elton Santos




