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

SQL年月范围查询逻辑错误求助:筛选结果不符合预期

问题描述

现有month和year两列,查询语句在特定参数下返回结果不符合预期:

  • 当选择时间范围为4/2020到12/2022时,期望返回2020年4月至2022年12月的所有数据,但当前查询会移除每年的前4个月数据。
  • 示例:查询1/2020到12/2022时能返回正确全量数据;但查询4/2020到12/2022时,错误过滤掉了2021年全量及2022年3月数据,仅保留部分结果。

原错误代码

错误逻辑SQL

SELECT r.country_id, r.rate as rate, r.month, d.country_id, d.year, d.month as value 
FROM `data_prod` d 
INNER JOIN monthly_data r ON r.country_id = d.country_id AND r.year=d.year AND r.month=d.month 
WHERE d.country_id IN (160) 
AND d.year BETWEEN 2020 AND 2022 
AND r.year BETWEEN 2020 AND 2022 
AND d.month BETWEEN 4 AND 12 
ORDER BY d.year, d.month

原PHP拼接代码

$countryIds = $countries;
$month_clause = "AND d.month BETWEEN $selectedStartMonth AND $selectedEndMonth";
        
$query = "SELECT r.country_id, r.rate as rate, r.month, d.country_id, d.year, d.month as value
      FROM `data_prod` d
      INNER JOIN monthly_data r ON r.country_id = d.country_id AND r.year=d.year AND r.month=d.month 
      WHERE d.country_id IN (".implode(",",$countryIds).") 
      AND d.year BETWEEN $periodStart AND $periodEnd
      AND r.year BETWEEN $periodStart AND $periodEnd
      $month_clause
      ORDER BY d.year, d.month";

问题根源

原代码用d.month BETWEEN 起始月 AND 结束月对所有年份的月份做统一过滤,导致非起始年份的前几个月也被错误排除(比如2021年的1-3月、2022年的1-3月)。正确逻辑需要分年份处理时间范围:

  1. 起始年份:月份≥起始月份
  2. 中间年份:保留所有月份
  3. 结束年份:月份≤结束月份

修正后的代码

修正逻辑示例SQL

SELECT r.country_id, r.rate as rate, r.month, d.country_id, d.year, d.month as value 
FROM `data_prod` d 
INNER JOIN monthly_data r ON r.country_id = d.country_id AND r.year=d.year AND r.month=d.month 
WHERE d.country_id IN (160) 
AND (
    (d.year = 2020 AND d.month >= 4)
    OR (d.year > 2020 AND d.year < 2022)
    OR (d.year = 2022 AND d.month <= 12)
)
AND r.year BETWEEN 2020 AND 2022 
ORDER BY d.year, d.month

修正后的PHP拼接代码

$countryIds = $countries;
// 动态生成时间范围条件
$date_condition = "";
if ($periodStart == $periodEnd) {
    // 同一年份的情况
    $date_condition = "AND (d.year = $periodStart AND d.month BETWEEN $selectedStartMonth AND $selectedEndMonth)";
} else {
    $date_condition = "AND (";
    // 起始年份:月份≥开始月
    $date_condition .= "(d.year = $periodStart AND d.month >= $selectedStartMonth)";
    // 中间年份:保留所有月份(如果存在中间年份)
    if ($periodEnd - $periodStart > 1) {
        $date_condition .= " OR (d.year > $periodStart AND d.year < $periodEnd)";
    }
    // 结束年份:月份≤结束月
    $date_condition .= " OR (d.year = $periodEnd AND d.month <= $selectedEndMonth)";
    $date_condition .= ")";
}
        
$query = "SELECT r.country_id, r.rate as rate, r.month, d.country_id, d.year, d.month as value
      FROM `data_prod` d
      INNER JOIN monthly_data r ON r.country_id = d.country_id AND r.year=d.year AND r.month=d.month 
      WHERE d.country_id IN (".implode(",",$countryIds).") 
      AND r.year BETWEEN $periodStart AND $periodEnd
      $date_condition
      ORDER BY d.year, d.month";

额外提醒

直接将变量拼接进SQL存在SQL注入风险,建议使用PHP的PDO或mysqli的参数绑定功能替代字符串拼接,提升代码安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:16:14