SQLazy:向前填充 NULL 值
问题描述
一张表记录了员工信息,包含 id(排序键)、name(姓名)、dept(部门)三个字段。现在要将 dept 列中的 NULL 值向前填充,即:用同列中前一个非 NULL 值替换 NULL 值。
源数据
id |
name |
dept |
1 |
Sophia |
Marketing |
2 |
Rachel |
NULL |
3 |
John |
Sales |
4 |
Megan |
NULL |
5 |
Megan |
NULL |
6 |
Zack |
IT |
7 |
Jane |
NULL |
期望结果
id |
name |
dept |
1 |
Sophia |
Marketing |
2 |
Rachel |
Marketing |
3 |
John |
Sales |
4 |
Megan |
Sales |
5 |
Megan |
Sales |
6 |
Zack |
IT |
7 |
Jane |
IT |
以 id=4–5 为例(dept=NULL):取 id=3 的 dept 值 Sales 进行填充
SQLazy 分步实现
核心思路:先通过计算列生成一个逻辑分组标记 grp,该标记在遇到 dept 非 NULL 时递增,从而将连续的 NULL 行与其上方的非 NULL 行归入同一组。然后以 grp 为分区键,在每个分区内取唯一的非 NULL 值,实现分区内填充。
Name |
Anchor |
Statement |
t1 |
forwardFill |
sort id asc |
t2 |
compute if ((dept notnull) then 1 else 0) cum as grp |
|
t3 |
compute dept max as filled_dept; partition grp |
|
derive id, name, filled_dept as dept |
下面逐一解释这些步骤。
第 1 步:按 id 升序排序
sort id asc
将数据按 id 升序排列,确保记录按编号顺序处理,这是后续分组和填充的前提。

第 2 步:创建逻辑分组标记
compute if ((dept notnull) then 1 else 0) cum as grp
这是最核心的一步。用计算列功能配合跨行参数 cum(累计),对条件式 if ((dept notnull) then 1 else 0) 进行累计求和。当 dept 非 NULL 时累计 1(表示新分组的开始),为 NULL 时累计 0(延续当前分组不变)。累计结果 grp 的值在每次遇到非 NULL 时递增 1,从而将数据划分为多个分区。

第 3 步:按分区向前填充
compute dept max as filled_dept; partition grp
在 grp 分区内,用聚合功能 max 取 dept 的最大值。每个分区内只有第一个记录的 dept 有值(非 NULL),后面的都是 NULL,MAX 聚合函数会自动取到那个非 NULL 值,从而实现“向前填充”的效果。
partition grp 确保不同分组之间的填充互不影响。这样就实现了按 id 顺序将 NULL 值替换为前一个非 NULL 值。

第 4 步:用 derive 功能选择需要输出的字段
编译生成 SQL
确认上述 4 步逻辑后,SQLazy 编译器自动生成原生 SQL(这里是 MySQL 语法):
WITH t2 AS (
SELECT id, name, dept
, SUM(CASE
WHEN dept IS NOT NULL THEN 1
ELSE 0
END) OVER (ORDER BY CASE
WHEN id IS NULL THEN 1
ELSE 0
END, id ASC ROWS UNBOUNDED PRECEDING) AS grp
FROM forwardFill
)
t3 AS (
SELECT id, name, dept, grp
, MAX(dept) OVER (PARTITION BY grp) AS filled_dept
FROM t2
)
SELECT id, name, filled_dept AS dept
FROM t3
ORDER BY CASE
WHEN id IS NULL THEN 1
ELSE 0
END, id ASC
SQLazy 让你用业务语言描述逻辑,而不是用 SQL 语法写嵌套查询。分步计算将向前填充拆解为多个个独立步骤,每步可独立验证中间结果。条件累计(cum)自动生成分组号,比 SQL 的窗口函数加自关联写法更直观易懂。
官方链接
SQLazy 在线体验:sqlazy.com(免费,无需注册)
SQLazy 项目仓库:github.com/SPLWare/SQLazy

英文版 https://c.esproc.com/article/1784022748590