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: