ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

StarRocks years_diff 函数详解:计算两个日期/时间表达式之间的年份差

StarRocks years_diff 函数详解:计算两个日期/时间表达式之间的年份差 StarRocks years_diff 函数详解计算两个日期/时间表达式之间的年份差【免费下载链接】starrocksThe worlds 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本篇技术指南围绕 StarRocks 的years_diff日期时间函数展开系统讲解其语法、参数约束、返回值语义与精确到月的取整逻辑。读者读完本文后将掌握在 StarRocks 中使用years_diff计算两时间点年份差的正确写法理解底层实现原理与边界情况如年初未满整年、反向时间差、2 月 29 日等场景并能结合源码定位与测试用例进行验证。函数概述years_diff是 StarRocks 提供的日期时间date-time函数之一用于计算两个日期表达式之间的年份差值结果为expr1 − expr2精确到年。该函数属于 StarRocks 后端BE向量化表达式引擎中的时间函数族声明位于 time_functions.h 第 533 行DEFINE_VECTORIZED_FN(years_diff)其文档位于 years_diff.md。从源码结构看years_diff与months_diff、quarters_diff属于同一族差值函数在 time_functions.h 中与years_diff_v2一并注册注释明确指出years_diff_v2等函数的语义与years_diff保持一致见第 415-419 行。years_diff常用于用户画像分析如统计用户注册至今的年限、账龄分桶、合约期限计算等按整年聚合的业务场景。语法与参数BIGINT years_diff(DATETIME expr1, DATETIME expr2);参数说明expr1结束时间必须是 DATETIME 或 DATE 类型expr2开始时间必须是 DATETIME 或 DATE 类型参数说明要点两个参数均支持DATETIME与DATE类型。当传入DATE时其隐含的时间部分被视为00:00:00如years_diff(2010-11-30, 2000-11-1)等价于比较两个零点时刻。函数计算方向为expr1 − expr2即返回结束时间相对开始时间过去了多少整年。若expr1早于expr2返回负值。返回值类型固定为BIGINT用于承载年份差值可能为负数。返回值语义函数返回BIGINT类型语义为正向差值expr1晚于expr2时返回正数表示满的整年数负向差值expr1早于expr2时返回负数未满一年若expr1与expr2之间的实际间隔不足一个完整年份即月份或日期尚未到达对应位置结果会向零取整truncate toward zero不产生小数部分非法日期如果输入的日期本身不存在例如2022-02-292022 年非闰年函数返回NULL。使用示例带时间部分的 DATETIME 参数select years_diff(2010-11-30 23:59:59, 2000-11-1 23:59:59); --------------------------------------------------------- | years_diff(2010-11-30 23:59:59, 2000-11-1 23:59:59) | --------------------------------------------------------- | 10 | ---------------------------------------------------------仅日期部分的 DATE 参数select years_diff(2010-11-30, 2000-11-1); --------------------------------------- | years_diff(2010-11-30, 2000-11-1) | --------------------------------------- | 10 | ---------------------------------------边界与反向差值的直观验证结合源码实现可以推演出以下典型边界结果读者可直接在 StarRocks 中执行验证查询预期结果说明years_diff(2021-01-01, 2021-03-02)0同一年内不足一整年取整为 0years_diff(2021-03-02, 2021-01-01)0反向仍不足一年years_diff(2021-12-31, 2021-01-01)0同年内即使跨 11 个月仍为 0years_diff(2023-01-01, 2021-03-02)1跨年但未满两年取整为 1years_diff(2021-03-02, 2023-01-01)-1反向差值返回负数底层实现原理源码级分析years_diff的核心实现位于 time_functions.cpp 的years_diffImpl第 1211-1233 行并通过DEFINE_TIME_BINARY_FN(years_diff, TYPE_DATETIME, TYPE_DATETIME, TYPE_BIGINT)第 1235 行注册为接收两个DATETIME、返回BIGINT的二元向量化函数。其计算逻辑可分解为三步拆解时间分量调用TimestampValue::to_timestamp将左右操作数分别拆解为年、月、日、时、分、秒、微秒year1/2、month1/2、day1/2、hour1/2等。计算年份粗差值year year1 - year2得到仅按年份相减的初始结果。按月-日-时-分-秒-微秒字典序修正取整构造一个单调编码函数func(month, day, hour, minute, second, usec)将年内的时刻整体编码为一个大整数当year 0时若结束时刻的年内编码小于开始时刻的年内编码说明结束时间在年内尚未到达开始时间的对应位置即未满整年则year减 1当year 0时做对称处理若结束时刻的年内编码大于开始时刻则year加 1。这一修正即实现了向零取整、不足一年不计的语义。// be/src/exprs/time_functions.cpp 第 1211-1233 行核心逻辑摘录 DEFINE_BINARY_FUNCTION_WITH_IMPL(years_diffImpl, l, r) { int year1, month1, day1, hour1, minute1, second1, usec1; int year2, month2, day2, hour2, minute2, second2, usec2; l.to_timestamp(year1, month1, day1, hour1, minute1, second1, usec1); r.to_timestamp(year2, month2, day2, hour2, minute2, second2, usec2); int year (year1 - year2); // 将月/日/时/分/秒/微秒编码为大整数用于未满整年的字典序比较 const auto func [](int month, int day, int hour, int minute, int second, int usec) - int64_t { ... }; if (year 0) { year - (func(month1, day1, hour1, minute1, second1, usec1) func(month2, day2, hour2, minute2, second2, usec2)); } else if (year 0) { year (func(month1, day1, hour1, minute1, second1, usec1) func(month2, day2, hour2, minute2, second2, usec2)); } return year; }需要说明的是上述实现按年份差 年内时刻比较完成整年取整未对月份天数差异如平年 2 月 28 日与闰年 2 月 29 日做逐月逐日的特殊处理更精细的月末对齐语义由years_diff_v2第 1238-1291 行承担其内部使用DAYS_IN_MONTH数组结合闰年判断对 2 月在平年/闰年的天数差异进行了大量边界分支处理见第 1255-1286 行注释中的date_diff(year, 2017-02-28, 2016-02-29)等特殊场景。当前仓库中years_diff_v2的注册与years_diff并存见 time_functions.h 第 415-419 行读者若需要对齐月末的年份差语义可关注该变体。单元测试验证StarRocks 为years_diff提供了专项单元测试TimeFunctionsTest.yearsDiffTest位于 time_functions_test.cpp 第 751-854 行覆盖了以下关键场景未满整年返回 02001-11-01 00:30:30与2000-12-01 00:30:30相差不足一年断言结果为0正向整年差2002-12-01与2000-11-01相差两年有余断言结果为2反向差值为负2000-11-01与2001-12-01前者早于后者断言结果为-1同年时间对2021-01-01与2021-03-02、2021-01-01与2021-12-31等成对输入均断言为0且注释明确timestamps that share a year are less than one year apart in either direction同一自然年内的两个时间点无论方向差均不足一年跨年部分年份向零取整2023-01-01与2021-03-02断言为1反向断言为-1。测试通过TimestampValue::create构造时间值、以TimestampColumn组织列数据直接调用TimeFunctions::years_diff向量化入口并以ColumnHelper::cast_toTYPE_BIGINT校验结果从执行层印证了本文上述语义描述。实践注意事项参数顺序决定正负函数语义是expr1 − expr2统计距今多少整年时应写成years_diff(now(), 起始时间)统计距今负数未来时间同理。DATE 与 DATETIME 混用DATE参数会按00:00:00参与比较混用不会报错但精确到秒的边界判断如23:59:59仅在DATETIME下有意义。非法日期返回 NULL如2022-02-29平年无此日函数返回NULL需在业务侧做好空值处理。与同类函数的选型同一差值函数族还包括months_diff、quarters_diff以及语义对齐月尾的years_diff_v2按月、按季度粒度计算时请选用对应函数避免自行做乘法换算造成语义偏差。整年取整特性结果不会出现小数或四舍五入任何不满一年的间隔一律截断为零这与datediff按天数取整、timediff返回精确时长的语义均不同按需选用。如需查看更多日期时间函数的完整清单与语法说明可继续浏览 docs/en/sql-reference/sql-functions/date-time-functions 目录下的对应文档。【免费下载链接】starrocksThe worlds 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),仅供参考
返回列表