Variant(T1, T2, ...)
Этот тип представляет собой объединение других типов данных. Тип Variant(T1, T2, ..., TN)
означает, что каждая строка этого типа
имеет значение либо типа T1
, либо T2
, либо ... либо TN
, либо ни одного из них (значение NULL
).
Порядок вложенных типов не имеет значения: Variant(T1, T2) = Variant(T2, T1). Вложенные типы могут быть произвольными типами, за исключением Nullable(...), LowCardinality(Nullable(...)) и Variant(...) типов.
Не рекомендуется использовать подобные типы в качестве вариантов (например, разные числовые типы, такие как Variant(UInt32, Int64)
, или разные типы дат, такие как Variant(Date, DateTime)
),
так как работа с значениями таких типов может привести к неясности. По умолчанию создание такого типа Variant
приведет к исключению, но это можно включить с помощью настройки allow_suspicious_variant_types
Тип данных Variant является бета-функцией. Для его использования установите enable_variant_type = 1
.
Создание Variant
Использование типа Variant
в определении колонки таблицы:
Использование CAST из обычных колонок:
Использование функций if/multiIf
, когда аргументы не имеют общего типа (настройка use_variant_as_common_type
должна быть включена для этого):
Использование функций 'array/map', если элементы массива/значения карты не имеют общего типа (настройка use_variant_as_common_type
должна быть включена для этого):
Чтение вложенных типов Variant как подколонок
Тип Variant поддерживает чтение одного вложенного типа из колонки Variant, используя имя типа как подколонку.
Таким образом, если у вас есть колонка variant Variant(T1, T2, T3)
, вы можете читать подколонку типа T2
, используя синтаксис variant.T2
,
эта подколонка будет иметь тип Nullable(T2)
, если T2
может находиться внутри Nullable
, а иначе будет иметь просто T2
. Эта подколонка сохранит такой же размер, как и исходная колонка Variant
и будет содержать значения NULL
(или пустые значения, если T2
не может находиться внутри Nullable
)
во всех строках, в которых исходная колонка Variant
не имеет тип T2
.
Подколонки Variant также можно читать, используя функцию variantElement(variant_column, type_name)
.
Примеры:
Чтобы узнать, какой вариант хранится в каждой строке, можно использовать функцию variantType(variant_column)
. Она возвращает Enum
с именем типа варианта для каждой строки (или 'None'
, если строка равна NULL
).
Пример:
Преобразование между колонкой Variant и другими колонками
Существует 4 возможных преобразования, которые могут быть выполнены с колонкой типа Variant
.
Преобразование колонки String в колонку Variant
Преобразование из String
в Variant
выполняется путем парсинга значения типа Variant
из строкового значения:
Преобразование обычной колонки в колонку Variant
Возможно преобразование обычной колонки с типом T
в колонку Variant
, содержащую этот тип:
Примечание: Преобразование из типа String
всегда выполняется через парсинг. Если вам нужно преобразовать колонку String
в строковый вариант Variant
без парсинга, вы можете сделать следующее:
Преобразование колонки Variant в обычную колонку
Можно преобразовать колонку Variant
в обычную колонку. В этом случае все вложенные варианты будут преобразованы в целевой тип:
Преобразование Variant в другой Variant
Можно преобразовать колонку Variant
в другую колонку Variant
, но только если целевая колонка Variant
содержит все вложенные типы из оригинального Variant
:
Чтение типа Variant из данных
Все текстовые форматы (TSV, CSV, CustomSeparated, Values, JSONEachRow и т. д.) поддерживают чтение типа Variant
. Во время парсинга данных ClickHouse пытается вставить значение в наиболее подходящий тип варианта.
Пример:
Сравнение значений типа Variant
Значения типа Variant
могут сравниваться только с значениями одного и того же типа Variant
.
Результат оператора <
для значений v1
, имеющего подлежащий тип T1
, и v2
, имеющего подлежащий тип T2
, типа Variant(..., T1, ... T2, ...)
определяется следующим образом:
- Если
T1 = T2 = T
, результат будетv1.T < v2.T
(подлежащие значения будут сравниваться). - Если
T1 != T2
, результат будетT1 < T2
(имена типов будут сравниваться).
Примеры:
Если вам нужно найти строку с определенным значением Variant
, вы можете сделать одну из следующих вещей:
- Преобразовать значение в соответствующий тип
Variant
:
- Сравнить подколонку
Variant
с требуемым типом:
Иногда может быть полезно выполнить дополнительную проверку на тип варианта, так как подколонки с комплексными типами, такими как Array/Map/Tuple
, не могут находиться внутри Nullable
и будут иметь значения по умолчанию вместо NULL
в строках с различными типами:
Примечание: Значения вариантов с различными числовыми типами считаются разными вариантами и не сравниваются друг с другом, их имена типов сравниваются вместо этого.
Пример:
Примечание: по умолчанию тип Variant
не допускается в ключах GROUP BY
/ORDER BY
, если вы хотите использовать его, учтите его специальное правило сравнения и включите настройки allow_suspicious_types_in_group_by
/allow_suspicious_types_in_order_by
.
Функции JSONExtract с Variant
Все функции JSONExtract*
поддерживают тип Variant
: