Skip to main content

mergedJSONPatch

引入版本:v26.8.0 按照“后写入优先” (last-write-wins) 语义合并 JSON 值以完成聚合,在路径级别实现 RFC 7396 JSON Merge Patch 的核心合并 行为。 该聚合函数以三元组 (key, value, sorting_key) 的形式存储状态,其中每个 key (JSON 路径) 仅保留按 sorting_key 确定的最新有效记录。对于 JSON 类型以动态标量叶节点形式存储的路径,对象写入会被展平到 其后代路径中。祖先节点上的非对象 写入会遮蔽与之冲突的后代节点。 所有显式声明类型的路径 (通过 JSON(a Map(...))、JSON(a Tuple(...))、 JSON(a Variant(...))、JSON(a Dynamic) 等方式声明) 都会被视为原子值:整个路径的值 会直接被较新的 patch 替换,而不会进行深度合并。只有未声明类型的 (动态) 标量路径才遵循 RFC 7396 深度合并语义。 sort_key 决定每个 JSON 路径最终采用哪个值。sort_key 最大的行会被 保留。如果两个相互冲突的补丁的排序键相同,则结果取决于处理顺序:后 处理的补丁胜出。不应依赖 ORDER BY 来确定性地决定此类并列情况的结果。 限制 (继承自 ColumnObject) :
  1. Null 删除:补丁 {"key": null} 不会删除该键。ColumnObject 在插入时会丢弃 值为 null 的成员,因此该函数无法区分 “键不存在” 与 “键为 null”。
  2. 空对象替换:补丁 {"a": {}} 无法替换路径 a 上较旧的标量值或数组。 ColumnObject 会静默丢弃值为空对象 {} 的路径, 因此较新的补丁不起任何作用,旧值会被保留下来。
  3. 非 Nullable 类型化路径缺失:当 JSON 列以非 Nullable 类型声明类型化路径时 (例如 JSON(a UInt32)) ,省略 a 的行会以该类型的默认值存储 (例如 0) 。该聚合函数无法区分 “不存在” 与 “显式 写入了默认值”,因此省略 a 的较新补丁会静默覆盖较旧的 非零值。为避免此问题,请将类型化路径声明为 Nullable (例如 JSON(a Nullable(UInt32))) 。Nullable 类型化路径中的 null 会被视为 “路径不存在”,从而被正确跳过。
  4. 所有类型化路径均为原子性的:每个类型化路径 (Map(K,V)、JSON、Dynamic、Tuple(…)、 Variant(…)、Array(…) 或任何其他声明的类型) 都作为单个值存储。该 聚合函数会以原子方式替换整个值,而不会对其内容进行深度合并。 只有动态 (无类型、标量) 路径才会逐路径进行深度合并。
  5. 键中点号的歧义:JSON 类型会用相同的内部路径 a.b 表示 {"a":{"b":1}} 和 {"a.b":1}。 因此,同一行可能同时将 a 和 a.b 作为 相互独立的同级路径暴露出来。当较新的补丁只写入 a 时,祖先/后代冲突 规则会清除 a.b;当它只写入 a.b 时,同一规则会清除 a。为避免此问题, 请设置 json_type_escape_dots_in_keys = 1。启用该设置后,JSON 键中的字面点号 会进行百分号编码 (例如 a.b 变为 a%2Eb) ,从而与嵌套 路径区分开来,消除这种误判的冲突。
语法
参数
  • json — 要聚合的 JSON 列。JSON
  • sort_key — 可比较的列,用于决定每个路径以哪次写入为准。将保留 sort_key 值最大的行。
返回值 返回将所有输入 JSON 对象合并后得到的单个 JSON 对象。 JSON 示例 使用排序键的基本用法
Query
Response
最后修改于 2026年10月14日