MySQL使用LAG函数获取表最后一个非空值替换空值失败如何解决
现有代码失效原因
- 分区规则错误:你的窗口函数PARTITION BY包含了
ticket_id、business_area、priority、client_name、closed_date、Closed_Date_ID六个字段,这会导致几乎每一行都被划分到独立的分区中,LAG函数只能读取同分区内的前一行数据,自然无法获取到其他行的非空Next_Create_date值。 - LAG函数局限性:LAG只能读取紧邻的上一行数据,如果存在连续多个空值行,只能填充第一个空值,后续空值依然无法匹配到最近的非空值。
- 排序规则错误:窗口内按
Next_Create_date desc排序逻辑不合理,空值排序优先级会导致你无法正确匹配到最近的非空日期。
正确实现方案
MySQL 8.0及以上版本可以使用带IGNORE NULLS参数的LAST_VALUE窗口函数,直接取当前行之前最近的非空Next_Create_date值,你可以根据实际业务逻辑调整分区规则(以下示例假设你需要按ticket_id、business_area、priority、client_name分组,同组内按closed_date倒序排列填充空值):
SELECT ticket_id, business_area, priority, client_name, closed_date, closed_date_id, Next_Create_date, CASE WHEN Next_Create_date IS NULL AND Ticket_ID = 0 THEN LAST_VALUE(Next_Create_date) IGNORE NULLS OVER ( PARTITION BY ticket_id, business_area, priority, client_name ORDER BY closed_date DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ) ELSE Next_Create_date END AS Next_Create_date2 FROM ams_auto.No_Issue_Time_NM a ORDER BY closed_date DESC;
如果你使用的MySQL版本不支持IGNORE NULLS,可以用子查询先标记非空值的分组,再取对应分组的最大非空值:
WITH temp AS ( SELECT *, SUM(CASE WHEN Next_Create_date IS NOT NULL THEN 1 ELSE 0 END) OVER ( PARTITION BY ticket_id, business_area, priority, client_name ORDER BY closed_date DESC ) AS val_group FROM ams_auto.No_Issue_Time_NM ) SELECT ticket_id, business_area, priority, client_name, closed_date, closed_date_id, Next_Create_date, CASE WHEN Next_Create_date IS NULL AND Ticket_ID = 0 THEN MAX(Next_Create_date) OVER (PARTITION BY ticket_id, business_area, priority, client_name, val_group) ELSE Next_Create_date END AS Next_Create_date2 FROM temp ORDER BY closed_date DESC;
内容的提问来源于stack exchange,提问作者RosaNegra
相关产品推荐
相关产品推荐

