在 Hive SQL 里,UDTF 是 User-Defined Table-Generating Function 的缩写,也叫 用户自定义表生成函数。
-
作用:
普通的 UDF(User-Defined Function)是一行进一行出的(1→1),UDAF(User-Defined Aggregate Function)是多行进一行出(N→1),而 UDTF 是一行进多行出(1→N)。
也就是说,输入一条记录,它可以“拆解”或“展开”为多条记录。 -
常见例子:
Hive 自带的explode()就是一个 UDTF,它可以把数组或 map 展开成多行: -
特点:
-
只能用在
SELECT子句或LATERAL VIEW中。 -
每次返回的是一张虚拟表(可能包含多列多行)。
-
在 Hive 中实现 UDTF 需要继承
org.apache.hadoop.hive.ql.udf.generic.GenericUDTF。
-
| 类型 | 输入 → 输出 | 调用方式 | 典型例子 |
|---|---|---|---|
| UDF | 1 → 1 | SELECT my_func(col) |
upper() |
| UDAF | N → 1 | SELECT group_func(col) GROUP BY ... |
sum() |
| UDTF | 1 → N | SELECT ... FROM ... LATERAL VIEW my_func(col) |
explode() |
ANSI SQL 标准里并没有专门的“UDTF”这个术语或函数。
不过在 ANSI SQL 以及其他数据库实现中,有类似的功能,比如 table-valued function(表值函数,TVF):
-
PostgreSQL / SQL Server:
支持直接定义返回表的函数(返回多行多列),可以在FROM子句中调用。 -
Oracle:
可以通过 pipelined table function 来实现类似功能。 -
ANSI SQL 标准:
允许在FROM子句里调用能返回一组行的函数,但标准里叫 table function,不是 UDTF。
所以:
-
UDTF这个名字是 Hive 特有的命名,主要出现在 Hadoop 生态。 -
ANSI SQL 里对应的概念是 table-valued function,但名称不同,接口风格也可能不同。
什么是 table-valued function(TVF)
-
定义:返回“一张表(多行多列)”的函数。与普通标量函数(返回单个值)或聚合函数(多行→一行)不同,TVF 的返回值可以直接放进
FROM子句当成表来用。 -
调用位置:
FROM/JOIN子句中,像表或子查询一样参与过滤、联接、聚合。 -
相关特性(标准 SQL):
-
可以给函数结果取别名,并显式列出列名。
-
需要相关参数(引用左侧表的列)时,用
LATERAL(标准自 SQL:2008 起引入)来“相关调用”。 -
可以被嵌套在其它查询中、再做
WHERE / GROUP BY / ORDER BY等操作。
-
名字上各家不同:Hive 叫 UDTF;标准里叫 table function;SQL Server 叫 TVF;Oracle 有 pipelined table function;本质一致:函数返回表。
标准式语法要点(概念模型)
注意:各数据库 DDL/语法细节不完全一致。下面先给“标准风格”的直觉,再给可运行的方言示例。
-
定义一个返回表的函数(概念)
-
在 FROM 中调用
-
与基表联接
-
相关(依赖左表列)调用:
LATERAL
-
TVF 内部也能是递归查询(标准的
WITH RECURSIVE),做通用“序列生成器”:
调用:
配合 LATERAL(相关子表):
典型使用场景
-
封装复杂子查询:把复杂业务逻辑包装成 TVF,
FROM tvf(args)处一行搞定,便于复用与测试。 -
对每行“展开”多行(1→N):例如“按阈值拆分”、“生成时间刻度/序列”、“多值参数展开”等。
-
依赖左表列的计算:用
LATERAL做“行级子查询”,比相关子查询更直观。 -
组合式数据管道:TVF 的输出再喂给下一个 TVF,形成可重用的查询管道。
各主流数据库的等价写法
下面每段都能直接运行(根据你所用数据库选择)。语义上都体现“函数返回表”。
PostgreSQL(最贴近标准、语法优雅)
定义 TVF(SQL 语言):
调用与联接:
相关调用(LATERAL):
SQL Server(T-SQL)
Inline TVF(推荐,性能好):
调用与联接:
相关调用(T-SQL 用 APPLY,等价于标准的 LATERAL):
Oracle
Pipelined Table Function(PL/SQL):可逐行“流式”产出,适合大表。
调用(注意 Oracle 的 TABLE()):
相关调用(Oracle 也支持 CROSS/OUTER APPLY,相当于 LATERAL):
实战范例小抄(可改造为你自己的库)
-
把“常用 TOP N 查询”封装为 TVF
-
好处:集中复用、改一个地方全系统受益、易加权限控制。
-
序列/日期刻度生成 TVF + LATERAL
-
生成每个用户注册日起的 7 天窗口:
-
用
seq(start, start+6)产出 7 行,再DATEADD/+ interval得到日期。 -
外层聚合即可统计“入职后一周的活跃”。
-
-
参数化维表展开
-
传入“阈值/标签/枚举”,TVF 返回命中的维度行;在事实表上按需
JOIN。
设计与性能建议
-
优先“内联/纯 SQL” TVF(比如 SQL Server 的 inline TVF、Postgres SQL 语言函数):优化器最容易下推谓词、做连接重排,通常比多语种(PL/pgSQL、T-SQL 多语句)更快。
-
尽量无副作用、不可变(deterministic):方便缓存与并行。
-
明确列名与类型:给 TVF 的结果显式列定义,调用时也给别名 + 列名列表,避免“列名漂移”。
-
与
LATERAL/APPLY配合:做“行相关”的 N 条明细展开时,语义直观、性能通常优于相关子查询。 -
权限与可观测性:TVF 是很好的逻辑边界,可以在函数层做授权、记录审计。

浙公网安备 33010602011771号