如何用前序有效值填充SQL中timesent字段的NULL值?
用前序非NULL值填充timesent字段的NULL值(简单解决方案)
你原查询的问题
你写的SELECT语句存在两个明显问题:
- 逻辑错误:
WHERE timesent < messages.timesent是同一个字段自身比较,无法关联到前序有效记录 - 语法错误:
and not null不符合SQL语法规范,正确判断非空应该用timesent IS NOT NULL
这就是为什么你的查询返回0条记录。
简单解决方案(分MySQL版本)
方案1:MySQL 8.0+(支持窗口函数)
使用LAST_VALUE窗口函数结合IGNORE NULLS,可以直接获取每条记录前序最后一个非NULL的timesent值。
先验证填充结果
SELECT channelid, messageid, timesent, -- 忽略NULL值,取当前行之前最后一个有效的timesent LAST_VALUE(timesent IGNORE NULLS) OVER (ORDER BY messageid) AS filled_timesent FROM messages;
更新表中的NULL值
确认填充结果符合预期后,执行以下语句更新原表:
UPDATE messages m JOIN ( SELECT messageid, LAST_VALUE(timesent IGNORE NULLS) OVER (ORDER BY messageid) AS filled_timesent FROM messages ) t ON m.messageid = t.messageid SET m.timesent = t.filled_timesent WHERE m.timesent IS NULL;
注意:
ORDER BY messageid是用来定义“前一条”的排序逻辑,如果你的业务是按插入时间或其他字段排序,替换成对应字段即可。
方案2:MySQL 8.0以下版本(用自定义变量)
如果你的MySQL版本不支持窗口函数,用自定义变量来保存前序非NULL值:
先验证填充结果
SELECT channelid, messageid, timesent, -- 当前值非空则更新变量,否则沿用变量的前序有效取值 @prev_time := IF(timesent IS NOT NULL, timesent, @prev_time) AS filled_timesent FROM messages, (SELECT @prev_time := NULL) init ORDER BY messageid;
更新表中的NULL值
UPDATE messages m JOIN ( SELECT messageid, @prev_time := IF(timesent IS NOT NULL, timesent, @prev_time) AS filled_timesent FROM messages, (SELECT @prev_time := NULL) init ORDER BY messageid ) t ON m.messageid = t.messageid SET m.timesent = t.filled_timesent WHERE m.timesent IS NULL;
内容的提问来源于stack exchange,提问作者vish
相关产品推荐
相关产品推荐

