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) :
-
Null 删除:补丁
{"key": null}不会删除该键。ColumnObject在插入时会丢弃 值为 null 的成员,因此该函数无法区分 “键不存在” 与 “键为 null”。 -
空对象替换:补丁
{"a": {}}无法替换路径a上较旧的标量值或数组。ColumnObject会静默丢弃值为空对象{}的路径, 因此较新的补丁不起任何作用,旧值会被保留下来。 -
非 Nullable 类型化路径缺失:当
JSON列以非 Nullable 类型声明类型化路径时 (例如JSON(a UInt32)) ,省略a的行会以该类型的默认值存储 (例如0) 。该聚合函数无法区分 “不存在” 与 “显式 写入了默认值”,因此省略a的较新补丁会静默覆盖较旧的 非零值。为避免此问题,请将类型化路径声明为Nullable(例如JSON(a Nullable(UInt32))) 。Nullable 类型化路径中的 null 会被视为 “路径不存在”,从而被正确跳过。 -
所有类型化路径均为原子性的:每个类型化路径 (
Map(K,V)、JSON、Dynamic、Tuple(…)、Variant(…)、Array(…)或任何其他声明的类型) 都作为单个值存储。该 聚合函数会以原子方式替换整个值,而不会对其内容进行深度合并。 只有动态 (无类型、标量) 路径才会逐路径进行深度合并。 -
键中点号的歧义:
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 列。JSONsort_key— 可比较的列,用于决定每个路径以哪次写入为准。将保留 sort_key 值最大的行。
JSON
示例
使用排序键的基本用法
Query
Response