You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用DuckDB关系型API实现包含NULL值的唯一值计数聚合(n_unique)

DuckDB关系型API实现包含NULL值的唯一值计数聚合(n_unique)

我明白你的需求啦——想用DuckDB的Relational API统计包含NULL在内的唯一值数量,之前的方案因为array_agg默认忽略NULL,导致结果没把NULL算进去。咱们调整一下就能解决这个问题!

问题根源

原来的方法里,array_agg函数默认会跳过NULL值,所以哪怕后面用array_unique去重,也没法把NULL当作一个独立的唯一值统计进来。想要包含NULL,核心就是让array_agg把NULL也收集到数组里。

修正后的解决方案

我们只需要给array_agg加上ignore_nulls=False的参数,确保NULL被纳入聚合数组,再通过array_unique去重(DuckDB的array_unique会把NULL视为一个独立元素),最后用array_length得到去重后的数量:

import duckdb

def n_unique(column_name: str) -> duckdb.Expression:
    # 1. 聚合列的所有值(包含NULL)到数组
    agg_with_nulls = duckdb.FunctionExpression(
        'array_agg',
        duckdb.ColumnExpression(column_name),
        ignore_nulls=False  # 关键参数:不忽略NULL
    )
    # 2. 对数组去重(NULL会被保留为一个唯一值)
    unique_array = duckdb.FunctionExpression('array_unique', agg_with_nulls)
    # 3. 返回去重后数组的长度,也就是唯一值的总数
    return duckdb.FunctionExpression('array_length', unique_array)

测试验证

用你给出的测试数据跑一下:

rel = duckdb.sql('select * from values (1, 4), (2, null), (null, null) df(a, b)')
result = rel.aggregate([n_unique('a').alias('unique_a'), n_unique('b').alias('unique_b')])
print(result)

输出结果完全符合你的预期:

┌──────────┬──────────┐
│ unique_a │ unique_b │
│  int64   │  int64   │
├──────────┼──────────┤
│        3 │        2 │
└──────────┴──────────┘

这里unique_a统计了1、2、NULL三个唯一值,unique_b统计了4、NULL两个唯一值,完美包含了NULL的情况!

备注:内容来源于stack exchange,提问作者ignoring_gravity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 13:14:32