news 2026/9/18 20:00:14

StarRocks weeks_sub 函数详解:DATETIME 周数减法运算的原理与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
StarRocks weeks_sub 函数详解:DATETIME 周数减法运算的原理与实战

StarRocks weeks_sub 函数详解:DATETIME 周数减法运算的原理与实战

【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks

weeks_sub是 StarRocks 提供的日期时间函数,用于从一个DATETIME值中减去指定周数,是数据仓库中做周期回溯分析(如环比、滚动窗口、周期报表)的常用工具。本文将基于官方文档与仓库源码,完整讲解其语法、参数约束、返回值规则、典型用法,并深入其 BE(Backend)与 FE(Frontend)两侧的实现原理,帮助你正确、高效地使用该函数。

函数概览与语法

weeks_sub的官方语法定义如下(见 weeks_sub.md):

DATETIME weeks_sub(DATETIME expr1, INT expr2);
  • expr1:原始日期,必须为DATETIME类型;
  • expr2:需要减去的周数,必须为INT类型;
  • 返回值类型:DATETIME

从函数命名看,它与weeks_add(周数加法)互为逆运算,二者在 StarRocks 的日期时间函数族中是一组成对出现的接口。同族函数还包括years_add/years_submonths_add/months_subdays_add/days_subhours_add/hours_sub等,可统一参考 date-time-functions 目录下的对应文档。

参数详解

expr1:原始日期

expr1必须是DATETIME类型的值。在 SQL 中直接书写字符串字面量(如'2022-12-22')时,StarRocks 会按照默认的日期时间格式将其隐式转换为DATETIME,因此官方示例中可以直接传入字符串。如果传入的是DATE类型列,建议先用CASTstr_to_date等函数转换为DATETIME后再参与运算,以保证类型语义清晰。

expr2:周数

expr2INT类型,表示要减去的周数。需要注意两点:

  1. 正数表示向过去回溯weeks_sub(ts, 2)表示将ts向前(过去方向)拨回 2 周;
  2. 负数等价于加周:从底层实现看(下文「实现原理」会展开),减法是通过对时间值执行「加负数值」完成的,因此weeks_sub(ts, -2)weeks_add(ts, 2)效果一致。

返回值与边界情况

  • 正常返回DATETIME类型的结果,精确到秒,时间部分保持与输入一致;
  • 如果输入的日期不存在(例如'2022-02-29'这类非法日期),函数返回NULL
  • 传入NULL参数时返回NULL(遵循标准 SQL 的 NULL 传播语义)。

使用示例

官方示例

原文档给出的基准示例(可复制到 StarRocks 客户端直接执行):

select weeks_sub('2022-12-22',2); +----------------------------+ | weeks_sub('2022-12-22', 2) | +----------------------------+ | 2022-12-08 00:00:00 | +----------------------------+

2022-12-22减去 2 周(14 天),得到2022-12-08 00:00:00

扩展实战示例

结合周数与时间部分,可以进行更精细的周期回溯:

-- 带时间部分的 DATETIME 回溯 SELECT weeks_sub('2022-12-22 14:30:00', 2); -- 2022-12-08 14:30:00 -- 用负数实现「减负 = 加」,与 weeks_add 相互印证 SELECT weeks_sub('2022-12-20', -1); SELECT weeks_add('2022-12-20', 1); -- 两者结果一致,均为 2022-12-27 -- 与当前时间结合做「4 周前」分析 SELECT weeks_sub(NOW(), 4); -- 配合表列做周期对比:统计 4 周前的订单量 SELECT sum(case when dt >= weeks_sub('2022-12-22', 4) then amount else 0 end) AS this_period, sum(case when dt < weeks_sub('2022-12-22', 4) then amount else 0 end) AS prev_period FROM orders;

与加法版本对照,可参考 weeks_add.md 中的weeks_add('2022-12-20', 2)示例,两者语法完全对称,便于记忆。

底层实现原理

BE 侧:统一宏展开实现

在存储引擎侧,weeks_sub的向量化实现位于 time_functions.cpp。它并没有单独书写逻辑,而是与weeks_add一起通过宏DEFINE_TIME_ADD_AND_SUB_FN(weeks, TimeUnit::WEEK)生成:

  • 加法宏:timestamp_add<TimeUnit::WEEK>(timestamp, count)
  • 减法宏:timestamp_add<TimeUnit::WEEK>(timestamp, -count),即「减 n 周」被实现为「加上 -n 周」。

这意味着减法天然支持负数参数,且与加法共享同一套基于TimeUnit::WEEK的日历运算内核,能够正确处理跨月、跨年(如 12 月底减 4 周进入 11 月)以及闰年等日历边界。该函数在 time_functions.h 中以DEFINE_VECTORIZED_FN(weeks_sub)注册为向量化函数,可对整列数据批量执行,获得良好的列式处理性能。

FE 侧:常量折叠与单调性标记

在前端优化器中,weeks_sub被注册为可常量折叠的函数,定义于 ScalarOperatorFunctions.java:

@ConstantFunction(name = "weeks_sub", argTypes = {DATETIME, INT}, returnType = DATETIME, isMonotonic = true) public static ConstantOperator weeksSub(ConstantOperator date, ConstantOperator week) { return ConstantOperator.createDatetimeOrNull(date.getDatetime().minusWeeks(week.getInt())); }

关键点:

  • isMonotonic = true:函数是单调的,优化器可以利用该性质对涉及weeks_sub的谓词做范围推导(如把weeks_sub(dt, 1) >= '2022-01-01'改写为对dt的可索引范围),从而提升查询性能;
  • 常量折叠:当expr1为常量时,FE 会在执行前直接调用minusWeeks求出结果,避免运行时开销;
  • 该函数名同时在 FunctionSet.java 中登记,参与全局函数解析。

典型应用场景

  • 滚动周期报表:以周为单位回溯历史数据,如计算「本周 vs 四周前」的订单、活跃用户对比;
  • 数据清理与归档:按weeks_sub(create_time, N)圈定 N 周前的数据范围;
  • 时间窗口计算:与NOW()CURRENT_TIMESTAMP组合,动态生成如「近 4 周」「近 12 周」的分析窗口。

小结

weeks_sub语法简洁、语义直观,是 StarRocks 中做周粒度时间回溯的标准函数。在使用时注意两点:expr1保证为DATETIME语义、expr2INT(负数等价于做加法)。理解其「减法即加负」的实现本质与 FE 侧的单调性优化,可以帮助你在编写周期分析 SQL 时写出更高效、更可靠的查询。

【免费下载链接】starrocksThe world's fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks

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

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

HIXL 传输路径总览:三引擎识别、日志定位与性能统计解读

HIXL 传输路径总览&#xff1a;三引擎识别、日志定位与性能统计解读 【免费下载链接】hixl HIXL&#xff08;Huawei Xfer Library&#xff09;是一个灵活、高效的昇腾单边通信库&#xff0c;面向集群场景提供简单、可靠、高效的点对点数据传输能力。 项目地址: https://gitco…

作者头像 李华
网站建设 2026/9/18 19:55:29

MySQL 1093错误详解:解决UPDATE子查询同表限制的5种方案

折腾 MySQL 的人&#xff0c;谁没跟“错误代码 1093”打过照面呢。刚入行那会儿&#xff0c;我在一个订单表上跑 UPDATE&#xff0c;子查询里顺手就写了从同一张表取数&#xff0c;结果 Workbench 直接甩给我一句&#xff1a;You can‘t specify target table ‘tb‘ for updat…

作者头像 李华
网站建设 2026/9/18 19:53:52

oh-my-hermes:React Native 的 Hermes 引擎配置与性能调优实战

做移动端开发这几年&#xff0c;有一个感受越来越深&#xff1a;React Native 项目跑到后期&#xff0c;性能问题基本都出在 JavaScript 引擎这一层。启动变慢、内存上涨、列表滚动掉帧&#xff0c;排查半天往往发现不是业务代码的问题&#xff0c;而是引擎配置根本没被认真对待…

作者头像 李华