Impala中实现book等字段连续空值向下填充的SQL方法
问题原因
你的写法存在三个核心问题:
- 普通
lag()函数不传偏移参数时仅能获取上1行的数值,连续空值场景下,第二行及以后的空值取到的上一行本身就是null,无法实现向前追溯最近非空值的效果 - SQL别名写法错误,三个字段填充逻辑最后都错误别名成了book,执行会直接报错
- 直接用全量向前填充非空值的逻辑不符合你的需求:你需要仅填充
book_per_row=1的非空书籍记录到下一条非空书籍记录之间的空值,后续非空书籍如果book_per_row=0,不需要向后填充,直接全局取最近非空值会多填后面的空行。
注意:group是SQL保留关键字,查询时需要用反引号包裹,否则会报语法错误。
正确实现SQL
实现逻辑分三步:
- 给同用户的行为按时间升序生成稳定行号,标记数据顺序
- 筛选所有book非空的边界记录,用
lead()函数拿到每条边界记录对应的下一条边界的行号,确定每条边界的填充范围 - 左关联原数据和边界表,匹配到属于
book_per_row=1的边界覆盖范围内的空行,做字段填充即可
with base_rn as ( select *, row_number() over(partition by id order by time asc, action, `group`) as rn from your_table -- 替换为实际表名 ), border_info as ( select rn as start_rn, book, book_type, book_status, book_per_row, lead(rn) over(partition by id order by rn asc) as next_start_rn from base_rn where book is not null -- 标记所有book非空的边界行 ) select b.id, b.action, b.`group`, -- 填充book字段:匹配到填充范围就取边界值,否则取原始值 case when bo.start_rn is not null then bo.book else b.book end as book, -- 填充book_type字段 case when bo.start_rn is not null then bo.book_type else b.book_type end as book_type, -- 填充book_per_row:匹配到填充范围且原始值为null则填0,否则取原始值 case when bo.start_rn is not null and b.book_per_row is null then 0 else b.book_per_row end as book_per_row, -- 填充book_status字段 case when bo.start_rn is not null then bo.book_status else b.book_status end as book_status, b.time from base_rn b left join border_info bo on bo.book_per_row = 1 -- 仅匹配book_per_row=1的起始填充边界 and b.rn > bo.start_rn -- 当前行在边界行之后 and b.rn < bo.next_start_rn -- 当前行在下一个边界行之前 order by b.rn asc;
结果验证
用你提供的样例数据执行上述SQL,会完全匹配期望结果:
- 6/29的buy记录(book_per_row=1)到7/4的search记录之间的4条空行会被正确填充,空的
book_per_row自动填0 - 7/4的search记录
book_per_row=0,不会触发向后填充,后续空行保持null - 第一条非空记录之前的所有空行保持null,符合需求。
内容的提问来源于stack exchange,提问作者DrGenius
相关产品推荐
相关产品推荐

