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
Используя тип 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 и другими колонками
С колонкой типа Variant можно выполнить 4 возможных преобразования.
Преобразование колонки String в колонку Variant
Преобразование из String в Variant выполняется путем парсинга значения типа Variant из строкового значения:
Чтобы отключить парсинг при преобразовании из String в Variant, вы можете отключить настройку cast_string_to_dynamic_use_inference:
Преобразование обычной колонки в колонку Variant
Возможно преобразовать обычную колонку с типом T в колонку Variant, содержащую этот тип:
Примечание: преобразование из типа String всегда выполняется через парсинг, если вам нужно преобразовать колонку 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: