Skip to main content

mergedJSONPatch

Добавлено в версии: 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), что отличает их от вложенных путей и устраняет ложный конфликт.
Синтаксис
Аргументы
  • json — JSON-столбец для агрегации. JSON
  • sort_key — столбец со сравнимыми значениями, определяющий, какая запись имеет приоритет для каждого пути. Сохраняется строка с наибольшим значением sort_key.
Возвращаемое значение Возвращает один объект JSON, полученный в результате слияния всех входных объектов JSON. JSON Примеры Базовое использование с ключом сортировки
Query
Response
Последнее изменение 14 октября 2026 г.