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 升序排列,确保记录按编号顺序处理,这是后续分组和填充的前提。

Picture1png

第 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,从而将数据划分为多个分区。

Picture2png

第 3 步:按分区向前填充

compute dept max as filled_dept; partition grp

在 grp 分区内,用聚合功能 max 取 dept 的最大值。每个分区内只有第一个记录的 dept 有值(非 NULL),后面的都是 NULL,MAX 聚合函数会自动取到那个非 NULL 值,从而实现“向前填充”的效果。

partition grp 确保不同分组之间的填充互不影响。这样就实现了按 id 顺序将 NULL 值替换为前一个非 NULL 值。

Picture3png

第 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