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

查询指定年月是否处于事件时间范围的SQL问题

解决月度事件报告的SQL查询问题

看起来你写的SQL条件逻辑搞反了,导致没法正确筛选出2019年4月范围内的事件。咱们先拆解问题,再一步步修正。

问题根源分析

你的需求是找出时间范围与2019年4月有重叠的事件——比如eventY(2019-03-11至2019-05-28)覆盖了4月,应该被选中;而eventX(2019-02-20至2019-03-15)完全在4月之前,应该被排除。

但原SQL的条件((year1 >= '$year') OR (year2 <= '$year')) AND ((month1 >= '$month') OR (month2 <= '$month'))逻辑完全错误:以eventY为例,代入$year=2019、$month=4后,(month1 >=4 OR month2 <=4)会变成(3>=4 OR5<=4),结果是false,最终整个条件为true AND false,直接把eventY排除了,完全不符合你的需求。

两种正确的查询方案

方案1:转换为日期范围比较(推荐,逻辑更直观)

把数据库里的year1/month1、year2/month2转换成具体的开始/结束日期,再和2019年4月的首尾日期做重叠判断——两个时间范围重叠的核心逻辑是:事件开始 ≤ 查询月结束,且事件结束 ≥ 查询月开始。

假设你的表结构中,year1是事件开始年份,month1是开始月份,year2是结束年份,month2是结束月份,SQL可以这么写:

SELECT * FROM eventi
WHERE
  -- 事件开始日期 ≤ 2019年4月最后一天
  CONCAT(year1, '-', LPAD(month1, 2, '0'), '-01') <= '2019-04-30'
  AND
  -- 事件结束日期 ≥ 2019年4月第一天
  LAST_DAY(CONCAT(year2, '-', LPAD(month2, 2, '0'), '-01')) >= '2019-04-01'

如果用变量动态传入年份和月份,可调整为:

$year = 2019;
$month = 4;
// 生成查询月的首尾日期
$month_start = "$year-" . str_pad($month, 2, '0', STR_PAD_LEFT) . "-01";
$month_end = date('Y-m-t', strtotime($month_start));

// 执行查询(安全优化见下方提醒)
$mainlink = mysqli_query($db,"SELECT * FROM eventi 
WHERE CONCAT(year1, '-', LPAD(month1, 2, '0'), '-01') <= '$month_end'
AND LAST_DAY(CONCAT(year2, '-', LPAD(month2, 2, '0'), '-01')) >= '$month_start'") 
or merror($msg = mysqli_error($db));

方案2:直接用年和月做逻辑判断

如果不想转换日期,也可以通过年和月的组合逻辑覆盖所有重叠场景:

SELECT * FROM eventi
WHERE
  -- 场景1:事件跨多年,完全包含查询年份(比如2018-2020)
  (year1 < $year AND year2 > $year)
  OR
  -- 场景2:事件开始和结束都在查询年份内,且覆盖查询月份
  (year1 = $year AND year2 = $year AND month1 <= $month AND month2 >= $month)
  OR
  -- 场景3:事件开始在查询年之前,结束在查询年且月份≥查询月
  (year1 < $year AND year2 = $year AND month2 >= $month)
  OR
  -- 场景4:事件开始在查询年且月份≤查询月,结束在查询年之后
  (year1 = $year AND year2 > $year AND month1 <= $month)

重要提醒:SQL注入风险

你现在直接把变量拼接到SQL语句里,存在严重的SQL注入风险!建议改用mysqli的预处理语句,示例如下:

$year = 2019;
$month = 4;
$month_start = "$year-" . str_pad($month, 2, '0', STR_PAD_LEFT) . "-01";
$month_end = date('Y-m-t', strtotime($month_start));

// 预处理语句
$stmt = mysqli_prepare($db, "SELECT * FROM eventi 
WHERE CONCAT(year1, '-', LPAD(month1, 2, '0'), '-01') <= ?
AND LAST_DAY(CONCAT(year2, '-', LPAD(month2, 2, '0'), '-01')) >= ?");
mysqli_stmt_bind_param($stmt, "ss", $month_end, $month_start);
mysqli_stmt_execute($stmt);
$mainlink = mysqli_stmt_get_result($stmt);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:36:37