基于最近时间更新Demo表ID的SQL语句报错(缺失表达式)求助
解决SQL更新ID字段的语法错误与需求实现问题
原SQL的错误分析
你的SQL语句存在多个语法和逻辑问题,导致"缺失表达式"错误:
- SET子句语法错误:
ID=select ...的写法不符合SQL规范,赋值用的子查询必须用括号()包裹,且子查询只能返回单个字段的单个值,不能同时返回多列 - 窗口函数逻辑错误:
PARTITION BY time完全不符合需求,你需要按ent name/review name分组来找到对应企业的最新时间记录,而不是按时间分组;且max(time)配合ORDER BY time ASC也无法帮你获取最新时间对应的ID - 子查询结构混乱:原SQL同时选取了
id, max(time), time1,id,name,time等多列,这会导致无法给单个ID字段赋值
符合需求的正确SQL实现
根据你的需求(按最新时间的ent name+AC代码更新同ent name+BC代码的ID,同理处理review name),以下是可行的实现方案(以Oracle为例,因为你使用了trunc(time)函数):
方案1:使用关联子查询(Oracle 12c+)
-- 1. 更新ent name对应的BC代码记录的ID UPDATE demo t1 SET t1.ID = ( -- 找到同ent name下AC代码的最新时间对应的ID SELECT t2.ID FROM demo t2 WHERE t2."ent name" = t1."ent name" AND t2.code = 'AC' ORDER BY t2.time DESC FETCH FIRST 1 ROW ONLY -- 取最新的一条记录 ) WHERE t1.code = 'BC'; -- 目标是BC代码的记录 -- 2. 同理更新review name对应的记录 UPDATE demo t1 SET t1.ID = ( SELECT t2.ID FROM demo t2 WHERE t2."review name" = t1."review name" AND t2.code = 'AC' -- 若review name对应的基准代码不同,可自行调整 ORDER BY t2.time DESC FETCH FIRST 1 ROW ONLY ) WHERE t1.code = 'BC'; -- 按需调整目标代码
方案2:使用窗口函数兼容旧版Oracle(12c以前)
-- 1. 更新ent name对应的BC代码记录 UPDATE demo t1 SET t1.ID = ( SELECT t2.ID FROM ( -- 给每个ent name的AC代码记录按时间倒序排号,最新的为1 SELECT ID, "ent name", ROW_NUMBER() OVER (PARTITION BY "ent name" ORDER BY time DESC) rn FROM demo WHERE code = 'AC' ) t2 WHERE t2."ent name" = t1."ent name" AND t2.rn = 1 ) WHERE t1.code = 'BC'; -- 2. 更新review name对应的记录 UPDATE demo t1 SET t1.ID = ( SELECT t2.ID FROM ( SELECT ID, "review name", ROW_NUMBER() OVER (PARTITION BY "review name" ORDER BY time DESC) rn FROM demo WHERE code = 'AC' ) t2 WHERE t2."review name" = t1."review name" AND t2.rn = 1 ) WHERE t1.code = 'BC';
注意事项
- 如果你的表中存在
ent name相同但没有AC代码记录的情况,子查询会返回NULL,此时ID会被更新为NULL,若要避免这种情况,可以在WHERE子句中加上AND EXISTS(...)判断 - 确保
time字段是日期类型,trunc(time)= '28-MAR-23'的写法依赖会话的日期格式,建议用trunc(time) = TO_DATE('2023-03-28', 'YYYY-MM-DD')来避免格式问题
内容的提问来源于stack exchange,提问作者user3873251
相关产品推荐
相关产品推荐

