news 2026/10/12 1:23:49

Apache Beam ZetaSQL 数学函数详解:MOD、CEIL、CEILING 与 FLOOR 的语义与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache Beam ZetaSQL 数学函数详解:MOD、CEIL、CEILING 与 FLOOR 的语义与实现
  • 批处理
  • 流处理
  • 大数据

【免费下载链接】beam

Apache Beam is a unified programming model for Batch and Streaming data processing.

项目地址:https://gitcode.com/gh_mirrors/beam15/beam
点击查看免费下载

本文以 Apache Beam ZetaSQL 官方文档(math-functions.md)为骨架,系统讲解 Beam ZetaSQL 内置数学函数中取模与取整四大家族函数(MOD、CEIL、CEILING、FLOOR)的语法、语义、类型签名与边界行为,并结合 Beam Java SDK 中 ZetaSQL 翻译模块的源码与测试用例,说明这些函数在查询计划阶段的底层映射与执行验证方式。读完本文,你将能准确区分向上取整与向下取整在正负数上的差异、掌握 MOD 结果符号规则,并能在自己的 Beam SQL 管线中正确使用这些函数。

一、Beam ZetaSQL 与数学函数支持概览

Beam SQL 支持 ZetaSQL 语言的一个变体。ZetaSQL 是 Google 开源的分析型 SQL 方言,与 BigQuery 的 SQL 框架语法相近,因此 Beam ZetaSQL 特别适合用于读写 BigQuery 表的管线(参见 overview.md)。Beam ZetaSQL 的翻译实现位于 Java SDK 的sdks/java/extensions/sql/zetasql模块(build.gradle 中描述为 "ZetaSQL to Calcite translator",当前锁定 ZetaSQL 版本2022.04.1):它先将 ZetaSQL 语法解析成 ZetaSQL 的 Resolved AST,再翻译为 Apache Calcite 的关系代数计划,最终交由 Beam 的各执行引擎(Direct、Flink、Spark、Dataflow 等)运行。

在函数支持层面,SupportedZetaSqlBuiltinFunctions.java集中维护了 Beam ZetaSQL 当前支持的内置函数清单(SupportedZetaSqlBuiltinFunctions.java)。文件中被注释掉的条目表示尚未支持,这是判断某个 ZetaSQL 函数能否在 Beam 中直接使用的权威依据。其中 "Math functions" 段落完整覆盖了本文要讲的四个函数:

  • FN_CEIL_DOUBLE(ceil(double) -> double)与FN_CEIL_NUMERIC(ceil(numeric) -> numeric),FN_CEIL_BIGNUMERIC未启用;
  • FN_FLOOR_DOUBLE与FN_FLOOR_NUMERIC,FN_FLOOR_BIGNUMERIC未启用;
  • FN_MOD_INT64(mod(int64, int64) -> int64)与FN_MOD_NUMERIC(mod(numeric, numeric) -> numeric),FN_MOD_BIGNUMERIC未启用。

同一清单中还包含 ABS、SIGN、ROUND、TRUNC、DIV、IS_INF、IS_NAN、IEEE_DIVIDE、SAFE_ADD/SUBTRACT/MULTIPLY/DIVIDE/NEGATE、SQRT、POW、EXP、LN、LOG10、LOG 以及全套三角函数等数学函数,说明这些取模取整函数只是 Beam ZetaSQL 完整数学函数体系的一部分。

通用规则:NULL 传播语义

原文档明确了一条所有数学函数共用的通用规则:

如果任一输入参数为NULL,所有数学函数都返回NULL。

也就是说,MOD(NULL, 3)、CEIL(NULL)、FLOOR(NULL)的结果都是NULL而不是报错或返回默认值。这一行为与 SQL 标准的 NULL 传播(null propagation)语义一致,也意味着这些函数不会作为过滤器吞掉含 NULL 的行——结果行的对应字段值为 NULL。

二、MOD:取模运算

MOD(X, Y)

功能:返回X除以Y的余数。与原文档一致,Beam ZetaSQL 中MOD的结果符号与X相同(而不是与除数Y相同,这与某些编程语言中的取模定义不同)。

类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):

签名说明状态
MOD(INT64, INT64) -> INT64整数取模,返回 INT64✅ 支持
MOD(NUMERIC, NUMERIC) -> NUMERIC高精度数值取模✅ 支持
MOD(BIGNUMERIC, BIGNUMERIC) -> BIGNUMERIC更大范围数值取模❌ 未启用(源码注释)

底层映射:在查询翻译阶段,ZetaSQL 的函数调用mod会被映射为 Calcite 标准运算符表中的MOD运算符(见 SqlOperatorMappingTable.java),随后由 Calcite 的 SQL 执行器按该运算符语义求值。

测试验证(ZetaSqlMathFunctionsTest.java):

// INT64 类型:MOD(4, 2) = 0 String sql = "SELECT MOD(4, 2)"; // 期望结果:Row 中 f_int64 = 0L
// NUMERIC 类型:MOD(NUMERIC '1.23456e05', NUMERIC '5') = 1 String sql = "SELECT MOD(NUMERIC '1.23456e05', NUMERIC '5')"; // 期望结果:BigDecimal 值 "1"

易混淆点:MOD与同清单中的DIV(整除)是对偶关系——DIV(X, Y)返回整除的商,MOD(X, Y)返回余数,二者配合可以完成 "商 + 余数" 的整数分解计算。

三、CEIL / CEILING:向上取整

CEIL(X) CEILING(X)

功能:CEIL(X)返回不小于X的最小整数值,结果类型为FLOAT64;CEILING(X)是CEIL(X)的同义词,二者行为完全等价,可互换使用。

类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):

签名说明状态
CEIL(DOUBLE) -> DOUBLE双精度浮点向上取整✅ 支持
CEIL(NUMERIC) -> NUMERICNUMERIC 向上取整✅ 支持
CEIL(BIGNUMERIC) -> BIGNUMERIC—❌ 未启用(源码注释)

底层映射:ceil在 SqlOperatorMappingTable.java 中被映射为 Calcite 的SqlStdOperatorTable.CEIL;由于CEILING是CEIL的同义词,ZetaSQL 解析层会在函数签名解析阶段统一处理,两者最终走向相同的 Calcite 运算符。

测试验证(ZetaSqlMathFunctionsTest.java):

// FLOAT64 类型:CEIL(1.2) = 2.0,CEIL(-1.2) = -1.0 String sql = "SELECT CEIL(1.2), CEIL(-1.2)"; // 期望结果:2.0, -1.0
// NUMERIC 类型:CEIL(NUMERIC '1.23456e04') = 12346,CEIL(NUMERIC '-1.23456e04') = -12345 String sql = "SELECT CEIL(NUMERIC '1.23456e04'), CEIL(NUMERIC '-1.23456e04')";

注意负数场景:CEIL(-1.2) = -1.0,因为 -1.0 是"不小于 -1.2"的最小整数(-1 > -1.2);而CEIL(-2.3) = -2.0,同理。

四、FLOOR:向下取整

FLOOR(X)

功能:FLOOR(X)返回不大于X的最大整数值,结果类型为FLOAT64。

类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):

签名说明状态
FLOOR(DOUBLE) -> DOUBLE双精度浮点向下取整✅ 支持
FLOOR(NUMERIC) -> NUMERICNUMERIC 向下取整✅ 支持
FLOOR(BIGNUMERIC) -> BIGNUMERIC—❌ 未启用(源码注释)

底层映射:floor在 SqlOperatorMappingTable.java 中被映射为 Calcite 的SqlStdOperatorTable.FLOOR。

测试验证(ZetaSqlMathFunctionsTest.java):

// FLOAT64 类型:FLOOR(1.2) = 1.0,FLOOR(-1.2) = -2.0 String sql = "SELECT FLOOR(1.2), FLOOR(-1.2)"; // 期望结果:1.0, -2.0
// NUMERIC 类型:FLOOR(NUMERIC '1.23456e04') = 12345,FLOOR(NUMERIC '-1.23456e04') = -12346 String sql = "SELECT FLOOR(NUMERIC '1.23456e04'), FLOOR(NUMERIC '-1.23456e04')";

注意负数场景:FLOOR(-1.2) = -2.0,因为 -2.0 是"不大于 -1.2"的最大整数(-2 < -1.2);FLOOR(-2.3) = -3.0,FLOOR(-2.8) = -3.0。

五、CEIL 与 FLOOR 行为对照(官方示例)

原文档给出了 Cloud Dataflow SQL 取整函数行为示例表,完整覆盖了正数、负数、整数边界与零值,是理解向上/向下取整差异的最佳速查表:

输入 "X"CEIL(X)FLOOR(X)
2.02.02.0
2.33.02.0
2.83.02.0
2.53.02.0
-2.3-2.0-3.0
-2.8-2.0-3.0
-2.5-2.0-3.0
000

从表中可以提炼三条规律:

  1. 正数区间:CEIL向"正无穷"方向进位(2.3 → 3.0),FLOOR向"零"方向截断(2.8 → 2.0),二者只在输入恰为整数(如 2.0)时结果一致;
  2. 负数区间:方向恰好反转——CEIL(-2.3) = -2.0(向零靠拢),FLOOR(-2.3) = -3.0(远离零);这也是"不小于 X 的最小整数 / 不大于 X 的最大整数"定义的直接推论;
  3. 零值:CEIL(0) = 0、FLOOR(0) = 0,取整不改变符号与数值。

因此,若业务需要"四舍五入"式的对称行为,应使用同清单中的ROUND(X[, digits])函数(支持ROUND(double)、ROUND(double, int64)、ROUND(numeric)、ROUND(numeric, int64)等签名,见 SupportedZetaSqlBuiltinFunctions.java),而不要用CEIL/FLOOR。

六、类型系统与算术运算符的配合

Beam ZetaSQL 的数值类型体系中(详见>SELECT CEIL(price / 10.0) * 10 AS rounded_up, MOD(CAST(price AS INT64), 10) AS remainder FROM orders;

七、在 Beam 管线中验证这些函数

Beam ZetaSQL 的测试基础设施(ZetaSqlTestBase.java)展示了验证 SQL 行为的标准流程,也可作为你自行实验的模板:

  1. 通过JdbcDriver.connect(createBeamTableProvider(), PipelineOptionsFactory.create())建立 JDBC 会话并注册测试表(如table_with_numeric);
  2. 用Frameworks.newConfigBuilder()结合ZetaSQLQueryPlanner.getZetaSqlRuleSets()构建查询规划配置;
  3. 用ZetaSQLQueryPlanner(config).convertToBeamRel(sql)将 SQL 转为 Beam 关系节点;
  4. 用BeamSqlRelUtils.toPCollection(pipeline, beamRelNode)把计划物化为PCollection<Row>;
  5. 用PAssert.that(stream).containsInAnyOrder(...)断言输出行,并pipeline.run().waitUntilFinish()执行。

ZetaSqlMathFunctionsTest 正是沿这条链路为 INT64、FLOAT64、NUMERIC 三种类型分别验证了本文全部函数的数值结果(除上文列出的用例,还包括算术运算符、ABS、SIGN、ROUND、TRUNC、DIV、SAFE_* 系列、SQRT、POW、EXP、LN、LOG10、LOG、三角函数等,见 ZetaSqlMathFunctionsTest.java 全文)。你可以将SELECT中的表达式替换为自己的业务计算,把该测试类作为"SQL 语义的即插即用验证台"。

八、使用建议与限制说明

  • NULL 传播:所有数学函数对 NULL 输入返回 NULL,设计 CASE 分支或 COALESCE 时需留意;
  • BIGNUMERIC 不支持:MOD、CEIL、FLOOR的 BIGNUMERIC 签名在 SupportedZetaSqlBuiltinFunctions.java 中均为注释状态,超出 NUMERIC 精度范围的运算请改用 NUMERIC 或拆分为 FLOAT64 处理;
  • 取整方向:CEIL/FLOOR并非四舍五入;需要按小数位舍入请使用ROUND(X, digits),需要直接截断小数请使用TRUNC(X, digits);
  • 与 BigQuery 的兼容性:由于 ZetaSQL 与 BigQuery SQL 同源,在 Beam ZetaSQL 中写MOD/CEIL/FLOOR的经验可直接迁移到使用 BigQueryIO 的读写作业(见 overview.md)。

如需了解函数调用规则、词法与语法细节,可继续阅读同目录下的 syntax.md、lexical.md 与 operators.md。

  • 批处理
  • 流处理
  • 大数据

【免费下载链接】beam

Apache Beam is a unified programming model for Batch and Streaming data processing.

项目地址:https://gitcode.com/gh_mirrors/beam15/beam
点击查看免费下载
上一篇:wagmi useBlobBaseFee Hook 详解:在 React 应用中读取 Blob 基础费率
下一篇:RockGO定时器组件:TimeWheel在游戏服务器中的高效应用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 1:22:51

Cortex 安全部署指南:多租户认证、TLS 加固与漏洞披露机制

可观测性时序数据库后端指标监控 【免费下载链接】cortex A horizontally scalable, highly available, multi-tenant, long term Prometheus. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/cortex6/cortex 点击查看 免费下载 本篇指南围绕开源时序数据库 Cortex 的官…

作者头像 李华
网站建设 2026/10/12 1:22:17

Ant Design Blazor 图片组件 Image 全指南:展示、容错、占位与多图预览

前端UI组件设计系统 【免费下载链接】ant-design-blazor 基于 Ant Design 与 Blazor 的前端组件库。让开发者解放生产力&#xff0c;实现更大价值。 项目地址&#xff1a; https://gitcode.com/ant-design-blazor/ant-design-blazor 点击查看 免费下载 导读 本指南围绕 ant-d…

作者头像 李华
网站建设 2026/10/12 1:22:13

用大模型写代码做视频:7类技术路线与5个实战案例

1. 从"写代码"到"做视频"&#xff1a;这条技术路线到底在解决什么问题第一次听到"用大模型写代码来做视频"这个说法&#xff0c;很多人的反应是&#xff1a;这俩事儿挨着吗&#xff1f;写代码是文本生成&#xff0c;做视频是多媒体处理&#xff…

作者头像 李华
网站建设 2026/10/12 1:21:10

Muse Gadget SDK 深度拆解:智能硬件接入架构、实测与选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华