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

> Агрегирует значения JSON по семантике JSON Merge Patch с правилом «последняя запись побеждает» (last-write-wins).

# mergedJSONPatch

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

Добавлено в версии: v26.8.0

Агрегирует значения JSON, выполняя их слияние по принципу «побеждает последняя запись» (last-write-wins), и реализует базовую логику слияния
из RFC 7396 JSON Merge Patch на уровне путей.

Агрегатная функция хранит состояние в виде троек (key, value, sorting\_key), где для каждого ключа (JSON-пути)
сохраняется только последняя действующая запись согласно sorting\_key. Записи объектов уплощаются в
дочерние пути для тех путей, которые тип `JSON` хранит как динамические скалярные листовые узлы. Необъектные записи в родительские пути
затеняют конфликтующие с ними дочерние.

Каждый явно типизированный путь (объявленный с помощью `JSON(a Map(...))`, `JSON(a Tuple(...))`,
`JSON(a Variant(...))`, `JSON(a Dynamic)` и т. д.), обрабатывается как атомарное значение: значение пути
целиком заменяется более новым патчем, а не объединяется глубоким слиянием. Семантике глубокого слияния по RFC 7396
подчиняются только нетипизированные (динамические) скалярные пути.

Столбец sort\_key определяет, какое значение будет выбрано для каждого JSON-пути. Сохраняется строка с наибольшим значением sort\_key. Если у двух конфликтующих патчей значения ключа сортировки совпадают, результат зависит от порядка обработки:
побеждает патч, обработанный позже. Не стоит рассчитывать, что `ORDER BY` детерминированно разрешит такие ситуации.

ОГРАНИЧЕНИЯ (унаследованы от `ColumnObject`):

1. Удаление через null: патч `{"key": null}` не удаляет ключ. `ColumnObject` отбрасывает
   элементы со значением null при вставке, поэтому функция не может отличить "ключ отсутствует" от
   "ключ равен null".

2. Замена пустым объектом: патч `{"a": {}}` не может заменить более старое скалярное значение или массив
   по пути `a`. `ColumnObject` молча отбрасывает пути, значением которых является пустой объект `{}`,
   поэтому более новый патч ничего не меняет, и старое значение сохраняется.

3. Отсутствие типизированного пути с не-Nullable типом: если в JSON-столбце объявлен типизированный путь с
   типом, не допускающим NULL (например, `JSON(a UInt32)`), строка без `a` сохраняется со
   значением по умолчанию для этого типа (например, `0`). Агрегатная функция не может отличить "отсутствует" от "явно
   записано значение по умолчанию", поэтому более новый патч без `a` молча затирает более старое
   ненулевое значение. Чтобы избежать этого, объявляйте типизированные пути как `Nullable`
   (например, `JSON(a Nullable(UInt32))`). Значение null в типизированном пути, допускающем NULL, интерпретируется как
   "путь отсутствует" и корректно пропускается.

4. Все типизированные пути атомарны: каждый типизированный путь (`Map(K,V)`, `JSON`, `Dynamic`, `Tuple(…)`,
   `Variant(…)`, `Array(…)` или любой другой объявленный тип) хранится как единое значение.
   Агрегатная функция атомарно заменяет значение целиком, а не выполняет глубокое слияние его содержимого.
   Глубокое слияние по отдельным путям выполняется только для динамических (нетипизированных, скалярных) путей.

5. Неоднозначность точки в ключе: тип `JSON` представляет `{"a":{"b":1}}` и `{"a.b":1}`
   одним и тем же внутренним путём `a.b`. Поэтому одна строка может содержать одновременно `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`](/ru/reference/data-types/newjson)
* `sort_key` — столбец со сравнимыми значениями, определяющий, какая запись имеет приоритет для каждого пути. Сохраняется строка с наибольшим значением sort\_key.

**Возвращаемое значение**

Возвращает один объект JSON, полученный в результате слияния всех входных объектов JSON. [`JSON`](/ru/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}             │
└─────────────────────────────────┘
```
