MySQL仅按日维度筛选日期区间数据及存储过程统计咨询
解决MySQL按日维度筛选日期区间数据及存储过程统计问题
我来帮你搞定这两个问题——按日维度筛选日期区间数据,以及完善你写了一半的存储过程来统计符合条件的数据量。
一、按日维度筛选两个日期区间的数据
你的表用Metric_Year、Metric_Month、Metric_Day三个字段存日期,直接写year >= startYear and month >= startMonth这种条件很容易踩坑(比如跨年度或跨月的区间,比如从2023-10-15到2024-02-20,直接限制月份>=10且<=2就完全不对)。给你两种实用方案:
方案1:拼接成DATE类型做区间比较(简单直观)
把三个字段拼成标准日期字符串,转成DATE类型后用BETWEEN筛选,逻辑清晰不容易错:
SELECT * FROM SOMT_Development.Board_Metrics_Data bmd WHERE STR_TO_DATE( CONCAT(bmd.Metric_Year, '-', LPAD(bmd.Metric_Month, 2, '0'), '-', LPAD(bmd.Metric_Day, 2, '0')), '%Y-%m-%d' ) BETWEEN '2023-01-01' AND '2024-06-30' AND bmd.Board_Metrics_ID = 1 AND bmd.Value_Colour = 'Red';
这里用LPAD给月份、日期补前导零(比如1月变成01),确保拼接后的字符串能正确转换成DATE类型。
方案2:纯逻辑判断(性能优先,适合大数据量)
如果担心函数转换导致索引失效,就用逻辑判断覆盖所有日期区间的情况,能利用Metric_Year、Metric_Month、Metric_Day的联合索引:
SELECT * FROM SOMT_Development.Board_Metrics_Data bmd WHERE ( -- 年份在起始年和结束年之间的所有数据 bmd.Metric_Year > startYear AND bmd.Metric_Year < endYear ) OR ( -- 起始年的有效数据:月份大于起始月,或者同月且日期>=起始日 bmd.Metric_Year = startYear AND ( bmd.Metric_Month > startMonth OR (bmd.Metric_Month = startMonth AND bmd.Metric_Day >= startDay) ) ) OR ( -- 结束年的有效数据:月份小于结束月,或者同月且日期<=结束日 bmd.Metric_Year = endYear AND ( bmd.Metric_Month < endMonth OR (bmd.Metric_Month = endMonth AND bmd.Metric_Day <= endDay) ) ) AND bmd.Board_Metrics_ID = 1 AND bmd.Value_Colour = 'Red';
二、完善存储过程统计数据量
从你给出的代码片段来看,你应该是想统计符合日期区间、指定Board_Metrics_ID和Value_Colour,并且属于最新Date_Created批次的数据量。下面是完整的存储过程实现:
完整存储过程代码
DELIMITER // CREATE PROCEDURE GetRedMetricCount( IN startYear INT, IN startMonth INT, IN startDay INT, IN endYear INT, IN endMonth INT, IN endDay INT, OUT resultCount INT ) BEGIN -- 先获取最新的Date_Created批次时间 DECLARE latestCreatedDate DATETIME; SELECT MAX(Date_Created) INTO latestCreatedDate FROM SOMT_Development.Board_Metrics_Data; -- 统计符合所有条件的数据量 SELECT COUNT(*) INTO resultCount FROM SOMT_Development.Board_Metrics_Data bmd WHERE -- 用方案2的逻辑做日期筛选,性能更好 ( bmd.Metric_Year > startYear AND bmd.Metric_Year < endYear ) OR ( bmd.Metric_Year = startYear AND ( bmd.Metric_Month > startMonth OR (bmd.Metric_Month = startMonth AND bmd.Metric_Day >= startDay) ) ) OR ( bmd.Metric_Year = endYear AND ( bmd.Metric_Month < endMonth OR (bmd.Metric_Month = endMonth AND bmd.Metric_Day <= endDay) ) ) AND bmd.Board_Metrics_ID = 1 AND bmd.Value_Colour = 'Red' AND bmd.Date_Created = latestCreatedDate; -- 匹配最新创建的批次 END // DELIMITER ;
调用存储过程的方式
传入参数后获取统计结果:
SET @count = 0; -- 示例:统计2023-01-01到2024-06-30的符合条件数据量 CALL GetRedMetricCount(2023, 1, 1, 2024, 6, 30, @count); SELECT @count AS Red_Metric_Count;
几个注意点
- 如果
Date_Created包含时分秒,建议改成DATE(bmd.Date_Created) = DATE(latestCreatedDate),避免因为时分秒的细微差异漏统计同一天的批次数据。 - 确保
Metric_Year、Metric_Month、Metric_Day是数值类型,别用字符串存储,不然比较逻辑会出问题。 - 数据量大的话,建议创建联合索引:
CREATE INDEX idx_metric_date_id_colour ON SOMT_Development.Board_Metrics_Data (Metric_Year, Metric_Month, Metric_Day, Board_Metrics_ID, Value_Colour);,能大幅提升查询速度。
内容的提问来源于stack exchange,提问作者dom sheratte
相关产品推荐
相关产品推荐

