
本文介绍使用 DuckDB 的列表推导式与 list_bool_or() 函数,高效筛选嵌套在 struct[] 列中、任一结构体字段满足子串匹配条件的行。
本文介绍使用 duckdb 的列表推导式与 list_bool_or() 函数,高效筛选嵌套在 struct[] 列中、任一结构体字段满足子串匹配条件的行。
在 DuckDB 中处理嵌套数据(如 struct(a VARCHAR, b VARCHAR)[] 类型的列表列)时,若需基于列表内任意元素的某个字段进行条件过滤(例如:保留所有 my_col 中至少有一个结构体的字段 b 包含子串 'bt' 的行),不能直接对列表列使用标量比较操作符。必须借助 DuckDB 提供的列表高阶函数与列表推导式完成“逐元素判断 → 聚合布尔结果 → 行级过滤”的逻辑。
核心思路是:
- 对每行的
my_col列(类型为struct[])执行列表推导式,遍历每个结构体s,判断s.b是否包含子串'bt',生成布尔值列表; - 使用
list_bool_or()将该布尔列表聚合为单个布尔值(只要有一个TRUE即返回TRUE); - 在
WHERE子句中使用该聚合结果完成行级过滤。
以下是完整可运行示例:
import duckdb
rel = duckdb.sql("""
FROM VALUES
([{'a': 'foo', 'b': 'bta'}]),
([]),
([{'a': 'jun', 'b': 'jul'}, {'a':'nov', 'b': 'obt'}])
AS df(my_col)
SELECT *
WHERE list_bool_or(['bt' IN s.b FOR s IN my_col])
""")
print(rel)
输出结果符合预期:
┌──────────────────────────────────────────────┐
│ my_col │
│ struct(a varchar, b varchar)[] │
├──────────────────────────────────────────────┤
│ [{'a': foo, 'b': bta}] │
│ [{'a': jun, 'b': jul}, {'a': nov, 'b': obt}] │
└──────────────────────────────────────────────┘
✅ 关键说明:
-
['bt' IN s.b FOR s IN my_col]是 DuckDB 支持的列表推导式语法,等价于list_apply(my_col, s -> 'bt' IN s.b),返回一个布尔值列表(如[TRUE]、[]、[FALSE, TRUE]); -
list_bool_or()对布尔列表执行逻辑或聚合:空列表返回FALSE,非空列表中任一TRUE即返回TRUE——这正是“存在性判断”所需的行为; - 若需匹配字段
a(而非b),仅需将s.b改为s.a;若需大小写不敏感匹配,可结合LOWER():'bt' IN LOWER(s.b)。
⚠️ 注意事项:
-
list_bool_or()自 DuckDB v0.10.0 起稳定可用,确保使用较新版本(推荐 ≥ v0.10.2); - 列表推导式中的变量名(如
s)为临时绑定,作用域仅限于该表达式内; - 空列表
[]推导后得到空布尔列表,list_bool_or([])返回FALSE,因此第二行被正确排除。
通过组合列表推导式与布尔聚合函数,DuckDB 实现了简洁、声明式且高性能的嵌套结构条件筛选,无需展开(UNNEST)即可完成复杂行级逻辑判断。










