十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

StarRocks transform_values 函数详解:用 Lambda 表达式批量改写 Map 的值

StarRocks transform_values 函数详解:用 Lambda 表达式批量改写 Map 的值 StarRocks transform_values 函数详解用 Lambda 表达式批量改写 Map 的值【免费下载链接】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/starrockstransform_values是 StarRocks 自 v3.1 起提供的高阶 Map 函数它接收一个 Map 和一个 Lambda 表达式对 Map 中每一个键值对应用该表达式为每个条目生成新的值最终返回一个新的 Map——键保持不变值由 Lambda 表达式的求值结果决定。本文以官方文档docs/en/sql-reference/sql-functions/map-functions/transform_values.md为主体完整覆盖其语法、参数、返回值语义与示例并结合前端分析器FE Analyzer源码解释它在执行前的改写机制帮助读者既会写 SQL也理解其底层原理。函数概述与适用版本transform_values的核心用途当你拿到一个MAP类型列只想对其中所有“值”做统一变换缩放、类型转换、取默认值、拼接等而不想改动键时用它一行表达式即可完成避免逐行展开或 UDF 开发。版本要求v3.1 起支持来源transform_values 文档。它与同族的transform_keys改写键、map_filter过滤条目配套使用三者都是基于 Lambda 表达式 的高阶函数。在函数名注册层面该函数名定义于 FE 常量类 FunctionSet.javapublic static final String TRANSFORM_VALUES transform_values;语法官方文档给出的标准写法是 Lambda 表达式在前MAP transform_values(lambda_func, any_map)同时lambda_func也可以放在any_map之后两种参数顺序等价MAP transform_values(any_map, lambda_func)返回类型固定为MAP。参数说明参数说明any_map输入的 Map任意 Map 类型内部以AnyMapType参与类型推导lambda_func要施加到any_map每个条目上的 Lambda 表达式关于 Lambda 表达式本身StarRocks 使用-运算符读作 goes to左侧是输入参数右侧是表达式。多参数用括号包裹如(k, v) - k v来源Lambda 表达式文档。关键约束用于 Map 高阶函数的 Lambda 表达式必须带两个参数——第一个参数代表键key第二个参数代表值value。这是transform_values在返回值一节中明确写出的要求。Lambda 体的使用限制继承自 Lambda 表达式文档的通用约束几乎所有一元/标量函数都可在 Lambda 体内使用不支持子查询如x - 5 (SELECT 3)不支持聚合函数如x - min(y)不支持窗口函数与表函数不能在 Lambda 内引用关联列correlated columns。返回值与 NULL 语义返回值语义是这类高阶函数最容易踩坑的部分官方文档逐条说明如下返回一个 Map其中值的类型由 Lambda 表达式的结果类型决定键的类型与any_map中键的类型相同键本身不被改写任一输入参数为 NULL 时整个函数返回 NULL——例如any_map列为 NULL或 Lambda 表达式整体为 NULL 字面量导致的参数级 NULL原始 Map 内部某个键或值为 NULL 时NULL 被视为普通值正常参与计算不会使整个结果变为 NULL——这一点对含 NULL 的脏数据处理非常重要Lambda 表达式必须有两个参数第一个是键第二个是值。官方示例构造含 NULL 键值的 Map 并统一改写官方示例先用 map_from_arrays 构造测试数据{1:ab,3:cdd,2:null,null:abc}键数组[1,3,null,2,null]与值数组[ab,cdd,null,null,abc]一一配对注意map_from_arrays允许键或值为 NULL 的条目存在然后把 Lambda 表达式应用到每个条目上第一个示例把每个条目的值统一改为1第二个示例把每个条目的值统一改为NULL。mysql select transform_values((k,v)-1, col_map) from (select map_from_arrays([1,3,null,2,null],[ab,cdd,null,null,abc]) as col_map)A; ---------------------------------------- | transform_values((k, v) - 1, col_map) | ---------------------------------------- | {1:1,3:1,2:1,null:1} | ---------------------------------------- 1 row in set (0.02 sec) mysql select transform_values((k,v)-null, col_map) from (select map_from_arrays([1,3,null,2,null],[ab,cdd,null,null,abc]) as col_map)A; -------------------------------------------- | transform_values((k, v) - NULL, col_map) | -------------------------------------------- | {1:null,3:null,2:null,null:null} | -------------------------------------------- 1 row in set (0.01 sec)从这两个示例可以验证上文 NULL 语义的两条规则示例 1 中键为NULL的条目null:abc也照常产出null:1说明NULL 键被当作普通值示例 2 中 Lambda 体是null字面量但结果是一整个全 NULL 值的 Map 而非整体 NULL说明Lambda 求值结果为 NULL 属于“条目级”语义只有作为整体输入参数为 NULL 才会导致函数返回 NULL。结合 Lambda 的键感知能力做实用变换由于 Lambda 能同时拿到键k和值v实践中可以写出比“纯值映射”更灵活的逻辑。以下写法由函数语义直接推导依据返回值一节中键透传、值取自 Lambda 结果的规则-- 值放大 2 倍INT 值域 SELECT transform_values((k, v) - v * 2, map_from_arrays([1, 3, 2], [10, 20, 30])); -- {1:20, 3:40, 2:60} -- 用 IF 表达式为 NULL 值填充默认值键保留 SELECT transform_values((k, v) - IF(v IS NULL, default, v), map_from_arrays([1, 3, 2], [ab, NULL, cd])); -- {1:ab, 3:default, 2:cd}第二例展示了transform_values的典型价值在不改动键的前提下对缺失值做兜底清洗且 NULL 值在 Lambda 体内可用IS NULL正常判断。源码视角transform_values 在 FE 中如何被改写执行文档层面它是“对 Map 的值应用 Lambda”但从源码结构看StarRocks 的 FE 分析器并没有为它单独实现一套执行路径而是把它改写rewrite为底层的map_apply高阶调用。改写逻辑位于 ExpressionAnalyzer.java 的 Lambda 函数分析分支中// lambda functions should be rewritten before visited if ((functionCallExpr.getFunctionName().equals(FunctionSet.MAP_FILTER)) || functionCallExpr.getFunctionName().equals(FunctionSet.TRANSFORM_VALUES)) { // (k,v) - expr (k,v) - (k,expr) Expr lambdaFunc functionCallExpr.getChild(0); LambdaArgument larg (LambdaArgument) lambdaFunc.getChild(1); Expr slotRef new SlotRef(null, larg.getName(), larg.getName()); lambdaFunc.setChild(0, new MapExpr(AnyMapType.ANY_MAP, Lists.newArrayList(slotRef, lambdaFunc.getChild(0)))); if (functionCallExpr.getFunctionName().equals(FunctionSet.TRANSFORM_VALUES)) { functionCallExpr.resetFnName(, FunctionSet.MAP_APPLY); } }这段代码揭示了三点实现事实键如何被“原样透传”对transform_values分析器把用户写的(k, v) - expr改写成(k, v) - {k: expr}的 Map 构造形式——用第一个参数键和 Lambda 原表达式的结果拼出一个单条目 Map再由map_apply合并这些条目。这与文档“键类型与输入相同、值类型由表达式决定”的语义一一对应统一收敛到 map_apply改写完成后函数名被替换为FunctionSet.MAP_APPLY即transform_values、map_filter等在运行时共享同一套高阶执行内核同分支下方对transform_keys的改写则是(k,v) - expr (k,v) - {expr: v}键取表达式、值透传可作为对照类型推导基于 Map 的键值类型改写前分析器会取出MapType的keyType与valueType并放入作用域作为 Lambda 输入占位见 ExpressionAnalyzer.java所以 Lambda 中k、v具有确定的静态类型v * 2之类的表达式可以在编译期完成类型检查。此外文档中“Lambda 可放在 Map 之后”的双参数顺序支持也体现在同文件对高阶函数参数位置的归一化分析中见 ExpressionAnalyzer.java 对TRANSFORM_VALUES的处理分支。使用建议与边界适用前提StarRocks v3.1 及以上输入必须是 Map 类型列或表达式否则分析期会报 “Lambda input should be a map” 类错误来源ExpressionAnalyzer.java 的类型检查逻辑。键值配对构造测试数据配合map_from_arrays(keys, values)构造含 NULL 的样本时注意两个数组必须等长否则该函数报错来源map_from_arrays 文档只改值不改键若需要同时改变键应改用同族的transform_keys若需要删除部分条目用map_filterNULL 心智模型参数级 NULL → 整体 NULL条目级 NULL → 普通值可按IS NULL处理。小结transform_values(lambda_func, any_map)让 StarRocks 用户可以用一行高阶函数完成“Map 值批量变换”键原样保留值由双参数 Lambda(k, v) - expr决定参数级 NULL 返回 NULL条目级 NULL 正常参与计算。源码层面它由 FE 分析器改写为map_apply的统一高阶执行路径理解这一点有助于把transform_values、transform_keys、map_filter作为同一套 Lambda Map 函数族来使用。【免费下载链接】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),仅供参考
返回列表