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

将MySQL查询时间间隔从23小时改为24小时触发ERROR 1242错误的排查与解决请求

解决ERROR 1242: Subquery returns more than 1 row的问题

错误根源分析

你遇到的这个错误和跨天其实没什么直接关系,核心问题是:当你把时间间隔从23小时改成24小时后,你的子查询返回了多条记录。SQL里像>= (子查询)这类比较操作,要求子查询必须返回恰好1行数据,否则就会触发1242错误。

之前用23小时的时候,DWNTIM表中符合start_date BETWEEN ...条件的记录刚好只有1条,所以子查询返回单行,和>=/<=的比较完全没问题;但改成24小时后,时间范围扩大,匹配到了多条shift记录,子查询返回多行,自然就触发了错误。

先验证问题

你可以单独执行其中一个出问题的子查询,确认返回行数:

SELECT cast(concat(start_date, ' ', (SEC_TO_TIME(start_time*60))) as datetime) 
FROM `austcor_map`.`DWNTIM` 
WHERE shift_id_number = 2 
  AND machine_number = 35 
  AND start_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)

如果返回行数大于1,就完全证实了这个问题。

具体解决方案

根据你的业务需求,有几种常见的修复方式:

1. 用聚合函数确保子查询返回单行

如果你需要取这个时间范围内最早的shift开始时间或者最晚的shift结束时间,可以用MIN()/MAX()聚合函数包裹子查询,强制返回单行值:

修改后的查询示例:

SELECT DATE_SUB(CURDATE(),INTERVAL 1 DAY) AS SHIFTDATE, t1.start_date_time, t1.end_date_time, 
CASE WHEN t1.start_date_time >= (
  SELECT MIN(cast(concat(start_date, ' ', (SEC_TO_TIME(start_time*60))) as datetime)) 
  FROM `austcor_map`.`DWNTIM` 
  WHERE shift_id_number = 2 AND machine_number = 35 
    AND start_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)
) 
AND t1.end_date_time <= (
  SELECT MAX(cast(concat(finish_date, ' ', (SEC_TO_TIME(finish_time*60))) as datetime)) 
  FROM `austcor_map`.`DWNTIM` 
  WHERE shift_id_number = 2 AND machine_number = 35 
    AND finish_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)
) 
THEN 'DAY' END AS Shift 
FROM `austcor_map`.`PDETLH` t1 
WHERE t1.start_date_time >= (
  SELECT MIN(cast(concat(start_date, ' ', (SEC_TO_TIME(start_time*60))) as datetime)) 
  FROM `austcor_map`.`DWNTIM` 
  WHERE shift_id_number = 2 AND machine_number = 35 
    AND start_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)
) 
AND t1.end_date_time <= (
  SELECT MAX(cast(concat(finish_date, ' ', (SEC_TO_TIME(finish_time*60))) as datetime)) 
  FROM `austcor_map`.`DWNTIM` 
  WHERE shift_id_number IN (2) AND machine_number = 35 
    AND finish_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)
) 
AND t1.corrugator_number = 1 
GROUP BY PROGRAM WITH ROLLUP

2. 用JOIN重构查询(更高效清晰)

你的查询里多次重复了相同的子查询,不仅效率低,也容易出错。可以用CTE(公共表表达式)先获取需要的shift时间范围,再通过JOIN关联查询:

WITH ShiftTimeRange AS (
  SELECT 
    MIN(cast(concat(start_date, ' ', (SEC_TO_TIME(start_time*60))) as datetime)) AS shift_start,
    MAX(cast(concat(finish_date, ' ', (SEC_TO_TIME(finish_time*60))) as datetime)) AS shift_end
  FROM `austcor_map`.`DWNTIM` 
  WHERE shift_id_number = 2 
    AND machine_number = 35 
    AND start_date BETWEEN (CURDATE()-INTERVAL 1 DAY) AND DATE_ADD((CURDATE()-INTERVAL 1 DAY), INTERVAL 24 HOUR)
)
SELECT 
  DATE_SUB(CURDATE(),INTERVAL 1 DAY) AS SHIFTDATE, 
  t1.start_date_time, 
  t1.end_date_time, 
  CASE WHEN t1.start_date_time >= str.shift_start AND t1.end_date_time <= str.shift_end THEN 'DAY' END AS Shift 
FROM `austcor_map`.`PDETLH` t1 
CROSS JOIN ShiftTimeRange str
WHERE t1.start_date_time >= str.shift_start 
  AND t1.end_date_time <= str.shift_end 
  AND t1.corrugator_number = 1 
GROUP BY PROGRAM WITH ROLLUP

3. 调整筛选条件(如果业务需要特定shift)

如果你的业务逻辑是只需要匹配某一个特定的shift,而不是时间范围内的所有shift,可以在DWNTIM的WHERE条件里添加更精确的筛选(比如特定的shift ID),确保子查询只返回单行数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:23:19