> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-detect-table-modification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> 按照“后写入优先”（last-write-wins）的 JSON Merge Patch 语义对 JSON 值进行聚合。

# mergedJSONPatch

<h2 id="mergedJSONPatch">
  mergedJSONPatch
</h2>

引入版本：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`) ，从而与嵌套
   路径区分开来，消除这种误判的冲突。

**语法**

```sql theme={null}
mergedJSONPatch(json, sort_key)
```

**参数**

* `json` — 要聚合的 JSON 列。[`JSON`](/zh/reference/data-types/newjson)
* `sort_key` — 可比较的列，用于决定每个路径以哪次写入为准。将保留 sort\_key 值最大的行。

**返回值**

返回将所有输入 JSON 对象合并后得到的单个 JSON 对象。 [`JSON`](/zh/reference/data-types/newjson)

**示例**

**使用排序键的基本用法**

```sql title=Query theme={null}
SELECT mergedJSONPatch(json, sort_key) FROM
(
    SELECT '{"a":1}'::JSON AS json, 1 AS sort_key
    UNION ALL
    SELECT '{"b":2}'::JSON, 2
    UNION ALL
    SELECT '{"a":3, "c":4}'::JSON, 3
);
```

```response title=Response theme={null}
┌─mergedJSONPatch(json, sort_key)─┐
│ {"a":3,"b":2,"c":4}             │
└─────────────────────────────────┘
```
