Базовые встроенные функции
- COALESCE
- LENGTH
- SUBSTRING
- FIND
- RFIND
- StartsWith, EndsWith
- IF
- NANVL
- Random...
- Udf
- CurrentUtc...
- CurrentTz...
- AddTimezone
- RemoveTimezone
- MAX_OF, MIN_OF, GREATEST и LEAST
- AsTuple, AsStruct, AsList, AsDict, AsSet, AsListStrict, AsDictStrict и AsSetStrict
- Литералы контейнеров
- Variant, AsVariant
- Enum, AsEnum
- AsTagged, Untag
- TablePath
- TableName
- TableRecordIndex
- TableRow
- FileContent и FilePath
- FolderPath
- ParseFile
- WeakField
- Ensure...
- AssumeStrict
- Likely
- Литералы простых типов
- ToBytes и FromBytes
- ByteAt
- ...Bit
- Abs
- Just, Unwrap, Nothing
- Callable
- Pickle, Unpickle
- StaticMap
- StaticZip
- AggregationFactory
- AggregateTransform...
- AggregateFlatten
Ниже описаны функции общего назначения, а для специализированных функций есть отдельные статьи: агрегатные, а также для работы со списками, словарями, структурами, типами данных.
COALESCE
Перебирает аргументы слева направо и возвращает первый найденный непустой аргумент. Чтобы результат получился гарантированно непустым (не optional типа), самый правый аргумент должен быть такого типа (зачастую используют литерал). При одном аргументе возвращает его без изменений.
Сигнатура
COALESCE(T?, ..., T)->T
COALESCE(T?, ..., T?)->T?
Позволяет передавать потенциально пустые значения в функции, которые не умеют обрабатывать их самостоятельно.
Доступен краткий формат записи в виде оператора ??
. Можно использовать алиас NVL
.
Примеры
SELECT COALESCE(
maybe_empty_column,
"it's empty!"
) FROM my_table;
SELECT
maybe_empty_column ?? "it's empty!"
FROM my_table;
SELECT NVL(
maybe_empty_column,
"it's empty!"
) FROM my_table;
(все три примера выше эквивалентны)
LENGTH
Возвращает длину строки в байтах. Также эта функция доступна под именем LEN
.
Сигнатура
LENGTH(T)->Uint32
LENGTH(T?)->Uint32?
Примеры
SELECT LENGTH("foo");
SELECT LEN("bar");
Примечание
Для вычисления длины строки в unicode символах можно воспользоваться функцией Unicode::GetLength.
Для получения числа элементов в списке нужно использовать функцию ListLength.
SUBSTRING
Возвращает подстроку.
Сигнатура
Substring(String[, Uint32? [, Uint32?]])->String
Substring(String?[, Uint32? [, Uint32?]])->String?
Обязательные аргументы:
- Исходная строка;
- Позиция — отступ от начала строки в байтах (целое число) или
NULL
, означающий «от начала».
Опциональные аргументы:
- Длина подстроки — количество байт, начиная с указанной позиции (целое число, или
NULL
по умолчанию, означающий «до конца исходной строки»).
Индексация с нуля. Если указанные позиция и длина выходят за пределы строки, возвращает пустую строку.
Если входная строка является опциональной, то таким же является и результат.
Примеры
SELECT SUBSTRING("abcdefg", 3, 1); -- d
SELECT SUBSTRING("abcdefg", 3); -- defg
SELECT SUBSTRING("abcdefg", NULL, 3); -- abc
FIND
Поиск позиции подстроки в строке.
Сигнатура
Find(String, String[, Uint32?])->Uint32?
Find(String?, String[, Uint32?])->Uint32?
Find(Utf8, Utf8[, Uint32?])->Uint32?
Find(Utf8?, Utf8[, Uint32?])->Uint32?
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Опциональные аргументы:
- Позиция — в байтах, с которой начинать поиск (целое число, или
NULL
по умолчанию, означающий «от начала исходной строки»).
Возвращает первую найденную позицию подстроки или NULL
, означающий что искомая подстрока с указанной позиции не найдена.
Примеры
SELECT FIND("abcdefg_abcdefg", "abc"); -- 0
SELECT FIND("abcdefg_abcdefg", "abc", 1); -- 8
SELECT FIND("abcdefg_abcdefg", "abc", 9); -- null
RFIND
Обратный поиск позиции подстроки в строке, от конца к началу.
Сигнатура
RFind(String, String[, Uint32?])->Uint32?
RFind(String?, String[, Uint32?])->Uint32?
RFind(Utf8, Utf8[, Uint32?])->Uint32?
RFind(Utf8?, Utf8[, Uint32?])->Uint32?
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Опциональные аргументы:
- Позиция — в байтах, с которой начинать поиск (целое число, или
NULL
по умолчанию, означающий «от конца исходной строки»).
Возвращает первую найденную позицию подстроки или NULL
, означающий, что искомая подстрока с указанной позиции не найдена.
Примеры
SELECT RFIND("abcdefg_abcdefg", "bcd"); -- 9
SELECT RFIND("abcdefg_abcdefg", "bcd", 8); -- 1
SELECT RFIND("abcdefg_abcdefg", "bcd", 0); -- null
StartsWith, EndsWith
Проверка наличия префикса или суффикса в строке.
Сигнатуры
StartsWith(Utf8, Utf8)->Bool
StartsWith(Utf8[?], Utf8[?])->Bool?
StartsWith(String, String)->Bool
StartsWith(String[?], String[?])->Bool?
EndsWith(Utf8, Utf8)->Bool
EndsWith(Utf8[?], Utf8[?])->Bool?
EndsWith(String, String)->Bool
EndsWith(String[?], String[?])->Bool?
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Аргументы могут быть типов String
или Utf8
и могут быть опциональными.
Примеры
SELECT StartsWith("abc_efg", "abc") AND EndsWith("abc_efg", "efg"); -- true
SELECT StartsWith("abc_efg", "efg") OR EndsWith("abc_efg", "abc"); -- false
SELECT StartsWith("abcd", NULL); -- null
SELECT EndsWith(NULL, Utf8("")); -- null
IF
Проверяет условие IF(condition_expression, then_expression, else_expression)
.
Является упрощенной альтернативой для CASE WHEN ... THEN ... ELSE ... END.
Сигнатура
IF(Bool, T, T)->T
IF(Bool, T)->T?
Аргумент else_expression
можно не указывать. В этом случае, если условие ложно (condition_expression
вернул false
), будет возвращено пустое значение с типом, соответствующим then_expression
и допускающим значение NULL
. Таким образом, у результата получится optional тип данных.
Примеры
SELECT
IF(foo > 0, bar, baz) AS bar_or_baz,
IF(foo > 0, foo) AS only_positive_foo
FROM my_table;
NANVL
Заменяет значения NaN
(not a number) в выражениях типа Float
, Double
или Optional.
Сигнатура
NANVL(Float, Float)->Float
NANVL(Double, Double)->Double
Аргументы:
- Выражение, в котором нужно произвести замену.
- Значение, на которое нужно заменить
NaN
.
Если один из агрументов Double
, то в выдаче Double
, иначе Float
. Если один из агрументов Optional
, то и в выдаче Optional
.
Примеры
SELECT
NANVL(double_column, 0.0)
FROM my_table;
Random...
Генерирует псевдослучайное число:
Random()
— число с плавающей точкой (Double) от 0 до 1;RandomNumber()
— целое число из всего диапазона Uint64;RandomUuid()
— Uuid version 4.
Сигнатуры
Random(T1[, T2, ...])->Double
RandomNumber(T1[, T2, ...])->Uint64
RandomUuid(T1[, T2, ...])->Uuid
При генерации случайных чисел аргументы не используются и нужны исключительно для управления моментом вызова. В каждый момент вызова возвращается новое случайное число. Поэтому:
- Повторный вызов Random в рамках одного запроса при идентичном наборе аргументов возвращает тот же самый набор случайных чисел. Важно понимать, что речь именно про сами аргументы (текст между круглыми скобками), а не их значения.
- Вызовы Random с одним и тем же набором аргументов в разных запросах вернут разные наборы случайных чисел.
Важно
Если Random используется в именованных выражениях, то его однократное вычисление не гарантируется. В зависимости от оптимизаторов и среды исполнения он может посчитаться как один раз, так и многократно. Для гарантированного однократного подсчета необходимо в этом случае материализовать именованное выражение в таблицу.
Сценарии использования:
SELECT RANDOM(1);
— получить одно случайное значение на весь запрос и несколько раз его использовать (чтобы получить несколько, можно передать разные константы любого типа);SELECT RANDOM(1) FROM table;
— одно и то же случайное число на каждую строку таблицы;SELECT RANDOM(1), RANDOM(2) FROM table;
— по два случайных числа на каждую строку таблицы, все числа в каждой из колонок одинаковые;SELECT RANDOM(some_column) FROM table;
— разные случайные числа на каждую строку таблицы;SELECT RANDOM(some_column), RANDOM(some_column) FROM table;
— разные случайные числа на каждую строку таблицы, но в рамках одной строки — два одинаковых числа;SELECT RANDOM(some_column), RANDOM(some_column + 1) FROM table;
илиSELECT RANDOM(some_column), RANDOM(other_column) FROM table;
— две колонки, и все с разными числами.
Примеры
SELECT
Random(key) -- [0, 1)
FROM my_table;
SELECT
RandomNumber(key) -- [0, Max<Uint64>)
FROM my_table;
SELECT
RandomUuid(key) -- Uuid version 4
FROM my_table;
SELECT
RANDOM(column) AS rand1,
RANDOM(column) AS rand2, -- same as rand1
RANDOM(column, 1) AS randAnd1, -- different from rand1/2
RANDOM(column, 2) AS randAnd2 -- different from randAnd1
FROM my_table;
Udf
Строит Callable
по заданному названию функции и опциональным external user types
, RunConfig
и TypeConfig
.
Udf(Foo::Bar)
— ФункцияFoo::Bar
без дополнительных параметров.Udf(Foo::Bar)(1, 2, 'abc')
— Вызов udfFoo::Bar
.Udf(Foo::Bar, Int32, @@{"device":"AHCI"}@@ as TypeConfig")(1, 2, 'abc')
— Вызов udfFoo::Bar
с дополнительным типомInt32
и указаннымTypeConfig
.Udf(Foo::Bar, "1e9+7" as RunConfig")(1, 'extended' As Precision)
— Вызов udfFoo::Bar
с указаннымRunConfig
и именоваными параметрами.
Сигнатуры
Udf(Callable[, T1, T2, ..., T_N][, V1 as TypeConfig][,V2 as RunConfig]])->Callable
Где T1
, T2
, и т. д. -- дополнительные (external
) пользовательские типы.
Примеры
$IsoParser = Udf(DateTime2::ParseIso8601);
SELECT $IsoParser("2022-01-01");
SELECT Udf(Unicode::IsUtf)("2022-01-01")
$config = @@{
"name":"MessageFoo",
"meta": "..."
}@@;
SELECT Udf(Protobuf::TryParse, $config As TypeConfig)("")
CurrentUtc...
CurrentUtcDate()
, CurrentUtcDatetime()
и CurrentUtcTimestamp()
- получение текущей даты и/или времени в UTC. Тип данных результата указан в конце названия функции.
Сигнатуры
CurrentUtcDate(...)->Date
CurrentUtcDatetime(...)->Datetime
CurrentUtcTimestamp(...)->Timestamp
Аргументы опциональны и работают по тому же принципу, что и у RANDOM.
Примеры
SELECT CurrentUtcDate();
SELECT CurrentUtcTimestamp(TableRow()) FROM my_table;
CurrentTz...
CurrentTzDate()
, CurrentTzDatetime()
и CurrentTzTimestamp()
- получение текущей даты и/или времени в указанной в первом аргументе IANA временной зоне. Тип данных результата указан в конце названия функции.
Сигнатуры
CurrentTzDate(String, ...)->TzDate
CurrentTzDatetime(String, ...)->TzDatetime
CurrentTzTimestamp(String, ...)->TzTimestamp
Последующие аргументы опциональны и работают по тому же принципу, что и у RANDOM.
Примеры
SELECT CurrentTzDate("Europe/Moscow");
SELECT CurrentTzTimestamp("Europe/Moscow", TableRow()) FROM my_table;
AddTimezone
Добавление информации о временной зоне к дате/времени, заданных в UTC. При выводе в результате SELECT
или после CAST
в String
будут применены правила временной зоны по вычислению смещения времени.
Сигнатура
AddTimezone(Date, String)->TzDate
AddTimezone(Date?, String)->TzDate?
AddTimezone(Datetime, String)->TzDatetime
AddTimezone(Datetime?, String)->TzDatetime?
AddTimezone(Timestamp, String)->TzTimestamp
AddTimezone(Timestamp?, String)->TzTimestamp?
Аргументы:
- Дата - тип
Date
/Datetime
/Timestamp
; - IANA имя временной зоны.
Тип результата - TzDate
/TzDatetime
/TzTimestamp
, в зависимости от типа данных входа.
Примеры
SELECT AddTimezone(Datetime("2018-02-01T12:00:00Z"), "Europe/Moscow");
RemoveTimezone
Удаление информации о временной зоне и перевод в дату/время, заданные в UTC.
Сигнатура
RemoveTimezone(TzDate)->Date
RemoveTimezone(TzDate?)->Date?
RemoveTimezone(TzDatetime)->Datetime
RemoveTimezone(TzDatetime?)->Datetime?
RemoveTimezone(TzTimestamp)->Timestamp
RemoveTimezone(TzTimestamp?)->Timestamp?
Аргументы:
- Дата - тип
TzDate
/TzDatetime
/TzTimestamp
.
Тип результата - Date
/Datetime
/Timestamp
, в зависимости от типа данных входа.
Примеры
SELECT RemoveTimezone(TzDatetime("2018-02-01T12:00:00,Europe/Moscow"));
MAX_OF, MIN_OF, GREATEST и LEAST
Возвращает минимальный или максимальный среди N аргументов. Эти функции позволяют не использовать стандартную для SQL конструкцию CASE WHEN a < b THEN a ELSE b END
, которая была бы особенно громоздкой для N больше двух.
Сигнатуры
MIN_OF(T[,T,...})->T
MAX_OF(T[,T,...})->T
Типы аргументов должны быть приводимы друг к другу и могут допускать значение NULL
.
GREATEST
является синонимом к MAX_OF
, а LEAST
— к MIN_OF
.
Примеры
SELECT MIN_OF(1, 2, 3);
AsTuple, AsStruct, AsList, AsDict, AsSet, AsListStrict, AsDictStrict и AsSetStrict
Создает контейнеры соответствующих типов. Также доступна операторная запись литералов контейнеров.
Особенности:
- Элементы контейнеров передаются через аргументы, таким образом число элементов результирующего контейнера равно числу переданных аргументов, кроме случая, когда повторяются ключи словаря.
- В
AsTuple
иAsStruct
могут быть вызваны без аргументов, а также аргументы могут иметь разные типы. - Имена полей в
AsStruct
задаются черезAsStruct(field_value AS field_name)
. - Для создания списка требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого списка с заданным типом элементов используется функция ListCreate. Можно создать пустой список как вызов
AsList()
без аргументов, в этом случае это выражение будет иметь типEmptyList
. - Для создания словаря требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого словаря с заданным типом элементов используется функция DictCreate. Можно создать пустой словарь как вызов
AsDict()
без аргументов, в этом случае это выражение будет иметь типEmptyDict
. - Для создания множества требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого множества с заданным типом элементов используется функция SetCreate. Можно создать пустое множество как вызов
AsSet()
без аргументов, в этом случае это выражение будет иметь типEmptyDict
. AsList
выводит общий тип элементов списка. При несовместимых типах генерируется ошибка типизации.AsDict
выводит раздельно общие типы ключей и значений. При несовместимых типах генерируется ошибка типизации.AsSet
выводит общие типы ключей. При несовместимых типах генерируется ошибка типизации.AsListStrict
,AsDictStrict
,AsSetStrict
требуют одинакового типа для аргументов.- В
AsDict
иAsDictStrict
в качестве аргументов ожидаютсяTuple
из двух элементов: ключ и значение, соответственно. Если ключи повторяются, в словаре останется только значение для первого ключа. - В
AsSet
иAsSetStrict
в качестве аргументов ожидаются ключи.
Примеры
SELECT
AsTuple(1, 2, "3") AS `tuple`,
AsStruct(
1 AS a,
2 AS b,
"3" AS c
) AS `struct`,
AsList(1, 2, 3) AS `list`,
AsDict(
AsTuple("a", 1),
AsTuple("b", 2),
AsTuple("c", 3)
) AS `dict`,
AsSet(1, 2, 3) AS `set`
Литералы контейнеров
Для некоторых контейнеров возможна операторная форма записи их литеральных значений:
- Кортеж —
(value1, value2...)
; - Структура —
<|name1: value1, name2: value2...|>
; - Список —
[value1, value2,...]
; - Словарь —
{key1: value1, key2: value2...}
; - Множество —
{key1, key2...}
.
Во всех случаях допускается незначащая хвостовая запятая. Для кортежа с одним элементом эта запятая является обязательной - (value1,)
.
Для имен полей в литерале структуры допускается использовать выражение, которое можно посчитать в evaluation time, например, строковые литералы, а также идентификаторы (в том числе в backticks).
Для списка внутри используется функция AsList, словаря - AsDict, множества - AsSet, кортежа - AsTuple, структуры - AsStruct.
Примеры
$name = "computed " || "member name";
SELECT
(1, 2, "3") AS `tuple`,
<|
`complex member name`: 2.3,
b: 2,
$name: "3",
"inline " || "computed member name": false
|> AS `struct`,
[1, 2, 3] AS `list`,
{
"a": 1,
"b": 2,
"c": 3,
} AS `dict`,
{1, 2, 3} AS `set`
Variant, AsVariant
Variant()
создает значение варианта над кортежем или структурой.
Сигнатура
Variant(T, String, Type<Variant<...>>)->Variant<...>
Аргументы:
- Значение
- Строка с именем поля или индексом кортежа
- Тип варианта
Пример
$var_type = Variant<foo: Int32, bar: Bool>;
SELECT
Variant(6, "foo", $var_type) as Variant1Value,
Variant(false, "bar", $var_type) as Variant2Value;
AsVariant()
создает значение варианта над структурой с одним полем. Это значение может быть неявно преобразовано к любому варианту над структурой, в которой совпадает для этого имени поля тип данных и могут быть дополнительные поля с другими именами.
Сигнатура
AsVariant(T, String)->Variant
Аргументы:
- Значение
- Строка с именем поля
Пример
SELECT
AsVariant(6, "foo") as VariantValue
Enum, AsEnum
Enum()
создает значение перечисления.
Сигнатура
Enum(String, Type<Enum<...>>)->Enum<...>
Аргументы:
- Строка с именем поля
- Тип перечисления
Пример
$enum_type = Enum<Foo, Bar>;
SELECT
Enum("Foo", $enum_type) as Enum1Value,
Enum("Bar", $enum_type) as Enum2Value;
AsEnum()
создает значение перечисления с одним элементом. Это значение может быть неявно преобразовано к любому перечислению, содержащему такое имя.
Сигнатура
AsEnum(String)->Enum<'tag'>
Аргументы:
- Строка с именем элемента перечисления
Пример
SELECT
AsEnum("Foo");
AsTagged, Untag
Оборачивает значение в Tagged тип данных с указанной меткой с сохранением физического типа данных. Untag
— обратная операция.
Сигнатура
AsTagged(T, tagName:String)->Tagged<T,tagName>
AsTagged(T?, tagName:String)->Tagged<T,tagName>?
Untag(Tagged<T, tagName>)->T
Untag(Tagged<T, tagName>?)->T?
Обязательные аргументы:
- Значение произвольного типа;
- Имя метки.
Возвращает копию значения из первого аргумента с указанной меткой в типе данных.
Примеры сценариев использования:
-
Возвращение на клиент для отображения в веб-интерфейсе медиа-файлов из base64-encoded строк.
-
Дополнительные уточнения на уровне типов возвращаемых колонок.
TablePath
Доступ к текущему имени таблицы, что бывает востребовано при использовании CONCAT, RANGE и других подобных механизмов.
Сигнатура
TablePath()->String
Аргументов нет. Возвращает строку с полным путём, либо пустую строку и warning при использовании в неподдерживаемом контексте (например, при работе с подзапросом или диапазоном из 1000+ таблиц).
Примечание
Функции TablePath, TableName и TableRecordIndex не работают для временных и анонимных таблиц (возвращают пустую строку или 0 для TableRecordIndex).
Данные функции вычисляются в момент выполнения проекции в SELECT
, и к этому моменту текущая таблица уже может быть временной.
Чтобы избежать такой ситуации, следует поместить вычисление этих функций в подзапрос, как это сделано во втором примере ниже.
Примеры
SELECT TablePath() FROM CONCAT(table_a, table_b);
SELECT key, tpath_ AS path FROM (SELECT a.*, TablePath() AS tpath_ FROM RANGE(`my_folder`) AS a)
WHERE key IN $subquery;
TableName
Получить имя таблицы из пути к таблице. Путь можно получить через функцию TablePath, или в виде колонки Path
при использовании табличной функции FOLDER.
Сигнатура
TableName()->String
TableName(String)->String
TableName(String, String)->String
Необязательные аргументы:
- путь к таблице, по умолчанию используется
TablePath()
(также см. его ограничения); - указание системы ("yt"), по правилам которой выделяется имя таблицы. Указание системы нужно только в том случае, если с помощью USE не указан текущий кластер.
Примеры
USE hahn;
SELECT TableName() FROM CONCAT(table_a, table_b);
SELECT TableName(Path, "yt") FROM hahn.FOLDER(folder_name);
TableRecordIndex
Доступ к текущему порядковому номеру строки в исходной физической таблице, начиная с 1 (зависит от реализации хранения).
Сигнатура
TableRecordIndex()->Uint64
Аргументов нет. При использовании в сочетании с CONCAT, RANGE и другими подобными механизмами нумерация начинается заново для каждой таблицы на входе. В случае использования в некорректном контексте возвращает 0.
Пример
SELECT TableRecordIndex() FROM my_table;
TableRow
Получение всей строки таблицы целиком в виде структуры. Аргументов нет.
Сигнатура
TableRow()->Struct
Пример
SELECT TableRow() FROM my_table;
FileContent и FilePath
Как консольный, так и веб-интерфейсы позволяют «прикладывать» к запросу произвольные именованные файлы. С помощью этих функций можно по имени приложенного файла получить его содержимое или путь в «песочнице» и в дальнейшем использовать в запросе произвольным образом.
Сигнатуры
FilePath(String)->String
FileContent(String)->String
Аргумент FileContent
и FilePath
— строка с алиасом.
Примеры
SELECT "Content of "
|| FilePath("my_file.txt")
|| ":\n"
|| FileContent("my_file.txt");
FolderPath
Получение пути до корня директории с несколькими «приложенными» файлами с указанным общим префиксом.
Сигнатура
FolderPath(String)->String
Аргумент — строка с префиксом среди алиасов.
Также см. PRAGMA File и PRAGMA Folder.
Примеры
PRAGMA File("foo/1.txt", "http://url/to/somewhere");
PRAGMA File("foo/2.txt", "http://url/to/somewhere/else");
PRAGMA File("bar/3.txt", "http://url/to/some/other/place");
SELECT FolderPath("foo"); -- в директории по возвращённому пути будут
-- находиться файлы 1.txt и 2.txt, скачанные по указанным выше ссылкам
ParseFile
Получить из приложенного текстового файла список значений. Может использоваться в сочетании с IN и прикладыванием файла по URL (инструкции по прикладыванию файлов для клиента).
Поддерживается только один формат файла — по одному значению на строку.
Сигнатура
ParseFile(String, String)->List<T>
Два обязательных аргумента:
- Тип ячейки списка: поддерживаются только строки и числовые типы;
- Имя приложенного файла.
Примечание
Возвращаемое значение - ленивый список. Для многократного использования его нужно обернуть в функцию ListCollect
Примеры:
SELECT ListLength(ParseFile("String", "my_file.txt"));
SELECT * FROM my_table
WHERE int_column IN ParseFile("Int64", "my_file.txt"));
WeakField
Вытаскивает колонку таблицы из строгой схемы, если оно там есть, либо из полей _other
и _rest
. В случае отсутствия значения возвращается NULL
.
Синтаксис: WeakField([<table>.]<field>, <type>[, <default_value>])
.
Значение по умолчанию используется только в случае отсутствия колонки в схеме данных. Чтобы подставить значение по умолчанию в любом случае можно воспользоваться COALESCE.
Примеры:
SELECT
WeakField(my_column, String, "no value"),
WeakField(my_table.other_column, Int64)
FROM my_table;
Ensure...
Проверка пользовательских условий:
Ensure()
— проверка верности предиката во время выполнения запроса.EnsureType()
— проверка точного соответствия типа выражения указанному.EnsureConvertibleTo()
— мягкая проверка соответствия типа выражения, работающая по тем же правилам, что и неявное приведение типов.
Если проверка не прошла успешно, то весь запрос завершается с ошибкой.
Сигнатуры
Ensure(T, Bool, String)->T
EnsureType(T, Type<T>, String)->T
EnsureConvertibleTo(T, Type<T>, String)->T
Аргументы:
- Выражение, которое станет результатом вызова функции в случае успеха проверки. Оно же подвергается проверке на тип данных в соответствующих функциях.
- В Ensure — булевый предикат, который проверяется на
true
. В остальных функциях — тип данных, который может быть получен через предназначенные для этого функции, либо строковый литерал с текстовым описанием типа. - Опциональная строка с комментарием к ошибке, которая попадет в общее сообщение об ошибке при завершении запроса. Для проверок типов не может использовать сами данные, так как они выполняются на этапе валидации запроса, а для Ensure — может быть произвольным выражением.
Для проверки условий по финальному результату вычисления Ensure удобно использовать в сочетании с DISCARD SELECT.
Примеры
SELECT Ensure(
value,
value < 100,
"value out or range"
) AS value FROM my_table;
SELECT EnsureType(
value,
TypeOf(other_value),
"expected value and other_value to be of same type"
) AS value FROM my_table;
SELECT EnsureConvertibleTo(
value,
Double?,
"expected value to be numeric"
) AS value FROM my_table;
AssumeStrict
Сигнатура
AssumeStrict(T)->T
Функция AssumeStrict
возвращает свой аргумент. Использование этой функции – способ сказать оптимизатору YQL, что выражение в аргументе является строгим, т.е. свободным от ошибок времени выполнения.
Большинство встроенных функций и операторов YQL являются строгими, но есть исключения – например Unwrap и Ensure.
Кроме того, нестрогим выражением считается вызов UDF.
Если есть уверенность, что при вычислении выражения ошибок времени выполнения на самом деле не возникает, то имеет смысл использовать AssumeStrict
.
Пример
SELECT * FROM T1 AS a JOIN T2 AS b USING(key)
WHERE AssumeStrict(Unwrap(CAST(a.key AS Int32))) == 1;
В данном примере мы считаем что все значения текстовой колонки a.key
в таблице T1
являются валидными числами, поэтому Unwrap не приводит к ошибке.
При налиичии AssumeStrict
оптимизатор сможет выполнить сначала фильтрацию, а потом JOIN.
Без AssumeStrict
такая оптимизация не выполняется – оптимизатор обязан учитывать ситуацию, при которой в колонке a.key
есть нечисловые значения, которые отфильтровываются JOIN
ом.
Likely
Сигнатура
Likely(Bool)->Bool
Likely(Bool?)->Bool?
Функция Likely
возвращает свой аргумент. Функция является подсказкой оптимизатору и говорит о том, что в большинстве случаев ее аргумент будет иметь значение True
.
Например, наличие такой функции в WHERE
означает что фильтр является слабоселективным.
Пример
SELECT * FROM T1 AS a JOIN T2 AS b USING(key)
WHERE Likely(a.amount > 0) -- почти всегда верно
При наличии Likely
оптимизатор не будет стараться выполнить фильтрацию перед JOIN
.
Литералы простых типов
Для простых типов могут быть созданы литералы на основании строковых литералов.
Синтаксис
<Простой тип>( <строка>[, <дополнительные атрибуты>] )
В отличие от CAST("myString" AS MyType)
:
- Проверка на приводимость литерала к требуемому типу происходит на этапе валидации;
- Результат не является optional.
Для типов данных Date
, Datetime
, Timestamp
и Interval
поддерживаются литералы только в формате, соответствующем ISO 8601. У Interval
есть следующие отличия от стандарта:
- поддерживается отрицательный знак для сдвигов в прошлое;
- микросекунды могут быть записаны как дробная часть секунд;
- единицы измерения больше недель не доступны;
- не поддерживаются варианты с началом/концом интервала, а также повторами.
Для типов данных TzDate
, TzDatetime
, TzTimestamp
литералы также задаются в формате, соответствующем ISO 8601, но вместо опционального суффикса Z через запятую указывается IANA имя временной зоны, например, GMT или Europe/Moscow.
Для параметрического типа данных Decimal дополнительно указывается два аргумента:
- общее число десятичных знаков (до 35, включительно);
- число десятичных знаков после запятой (из общего числа, то есть строго не больше предыдущего аргумента).
Примеры
SELECT
Bool("true"),
Uint8("0"),
Int32("-1"),
Uint32("2"),
Int64("-3"),
Uint64("4"),
Float("-5"),
Double("6"),
Decimal("1.23", 5, 2), -- до 5 десятичных знаков, из которых 2 после запятой
String("foo"),
Utf8("привет"),
Yson("<a=1>[3;%false]"),
Json(@@{"a":1,"b":null}@@),
Date("2017-11-27"),
Datetime("2017-11-27T13:24:00Z"),
Timestamp("2017-11-27T13:24:00.123456Z"),
Interval("P1DT2H3M4.567890S"),
TzDate("2017-11-27,Europe/Moscow"),
TzDatetime("2017-11-27T13:24:00,America/Los_Angeles"),
TzTimestamp("2017-11-27T13:24:00.123456,GMT"),
Uuid("f9d5cc3f-f1dc-4d9c-b97e-766e57ca4ccb");
ToBytes и FromBytes
Конвертация простых типов данных в строку со своим бинарным представлением и обратно. Числа представляются в little endian.
Сигнатуры
ToBytes(T)->String
ToBytes(T?)->String?
FromBytes(String, Type<T>)->T?
FromBytes(String?, Type<T>)->T?
Примеры
SELECT
ToBytes(123), -- "\u0001\u0000\u0000\u0000"
FromBytes(
"\xd2\x02\x96\x49\x00\x00\x00\x00",
Uint64
); -- 1234567890ul
ByteAt
Получение значение байта в строке по индексу от её начала. В случае некорректного индекса возвращается NULL
.
Сигнатура
ByteAt(String, Uint32)->Uint8
ByteAt(String?, Uint32)->Uint8?
ByteAt(Utf8, Uint32)->Uint8
ByteAt(Utf8?, Uint32)->Uint8?
Аргументы:
- Строка:
String
илиUtf8
; - Индекс:
Uint32
.
Примеры
SELECT
ByteAt("foo", 0), -- 102
ByteAt("foo", 1), -- 111
ByteAt("foo", 9); -- NULL
...Bit
TestBit()
, ClearBit()
, SetBit()
и FlipBit()
- проверить, сбросить, установить или инвертировать бит в беззнаковом числе по указанному порядковому номеру бита.
Сигнатуры
TestBit(T, Uint8)->Bool
TestBit(T?, Uint8)->Bool?
ClearBit(T, Uint8)->T
ClearBit(T?, Uint8)->T?
SetBit(T, Uint8)->T
SetBit(T?, Uint8)->T?
FlipBit(T, Uint8)->T
FlipBit(T?, Uint8)->T?
Аргументы:
- Беззнаковое число, над которым выполнять требуемую операцию. TestBit также реализован и для строк.
- Номер бита.
TestBit возвращает true/false
. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.
Примеры:
SELECT
TestBit(1u, 0), -- true
SetBit(8u, 0); -- 9
Abs
Абсолютное значение числа.
Сигнатура
Abs(T)->T
Abs(T?)->T?
Примеры
SELECT Abs(-123); -- 123
Just, Unwrap, Nothing
Just()
- Изменить тип данных значения на optional от текущего типа данных (то есть T
превращается в T?
).
Сигнатура
Just(T)->T?
Примеры
SELECT
Just("my_string"); -- String?
Unwrap()
- Преобразование значения optional типа данных в соответствующий не-optional тип с ошибкой времени выполнений, если в данных оказался NULL
. Таким образом, T?
превращается в T
.
Если значение не является optional, то функция возвращает свой первый аргумент без изменений.
Сигнатура
Unwrap(T?)->T
Unwrap(T?, Utf8)->T
Unwrap(T?, String)->T
Аргументы:
- Значение для преобразования;
- Опциональная строка с комментарием для текста ошибки.
Обратная операция — Just.
Примеры
$value = Just("value");
SELECT Unwrap($value, "Unexpected NULL for $value");
Nothing()
- Создать пустое значение указанного Optional типа данных.
Сигнатура
Nothing(Type<T?>)->T?
Примеры
SELECT
Nothing(String?); -- пустое значение (NULL) с типом String?
Подробнее о ParseType и других функциях для работы с типами данных.
Callable
Создать вызываемое значение с заданной сигнатурой из лямбда-функции. Обычно используется для того, чтобы размещать вызываемые значения в контейнерах.
Сигнатура
Callable(Type<Callable<(...)->T>>, lambda)->Callable<(...)->T>
Аргументы:
- Тип;
- Лямбда-функция.
Примеры:
$lambda = ($x) -> {
RETURN CAST($x as String)
};
$callables = AsTuple(
Callable(Callable<(Int32)->String>, $lambda),
Callable(Callable<(Bool)->String>, $lambda),
);
SELECT $callables.0(10), $callables.1(true);
Pickle, Unpickle
Pickle()
и StablePickle()
сериализуют произвольный объект в последовательность байт, если это возможно. Типовыми несериализуемыми объектами являются Callable и Resource. Формат сериализации не версионируется, допускается использовать в пределах одного запроса. Для типа Dict функция StablePickle предварительно сортирует ключи, а для Pickle порядок элементов словаря в сериализованном представлении не определен.
Unpickle()
— обратная операция (десериализация), где первым аргументом передается тип данных результата, а вторым — строка с результатом Pickle()
или StablePickle()
.
Сигнатуры
Pickle(T)->String
StablePickle(T)->String
Unpickle(Type<T>, String)->T
Примеры:
SELECT *
FROM my_table
WHERE Digest::MurMurHash32(
Pickle(TableRow())
) % 10 == 0; -- в реальности лучше использовать TABLESAMPLE
$buf = Pickle(123);
SELECT Unpickle(Int32, $buf);
StaticMap
Преобразует структуру или кортеж, применяя лямбду к каждому элементу.
Сигнатура
StaticMap(Struct<...>, lambda)->Struct<...>
StaticMap(Tuple<...>, lambda)->Tuple<...>
Аргументы:
- Структура или кортеж;
- Лямбда для обработки элементов.
Результат: структура или кортеж с аналогичным первому аргументу количеством и именованием элементов, а типы данных элементов определяются результатами лямбды.
Примеры:
SELECT *
FROM (
SELECT
StaticMap(TableRow(), ($item) -> {
return CAST($item AS String);
})
FROM my_table
) FLATTEN COLUMNS; -- преобразование всех колонок в строки
StaticZip
Поэлементно "склеивает" структуры или кортежи. Все аргументы (один и более) должны быть либо структурами с одинаковым набором полей, либо кортежами одинаковой длины.
Результататом будет соответственно структура или кортеж.
Каждый элемент результата – кортеж с соответствующими элементами из аргументов.
Сигнатура
StaticZip(Struct, Struct)->Struct
StaticZip(Tuple, Tuple)->Tuple
Примеры:
$one = <|k1:1, k2:2.0|>;
$two = <|k1:3.0, k2:4|>;
-- поэлементное сложение двух структур
SELECT StaticMap(StaticZip($one, $two), ($tuple)->($tuple.0 + $tuple.1)) AS sum;
AggregationFactory
Создать фабрику для агрегационных функций для того чтобы разделить процесс описания того, как агрегировать данные, и то, к каким данным это применять.
Аргументы:
- Строка в кавычках, являющаяся именем агрегационной функции, например "MIN".
- Опциональные параметры агрегационной функции, которые не зависят от данных. Например, значение percentile в PERCENTILE.
Полученную фабрику можно использовать как второй параметр функции AGGREGATE_BY.
Если агрегационная функция работает на двух колонках вместо одной, как например, MIN_BY, то в AGGREGATE_BY первым аргументом передается Tuple
из двух значений. Подробнее это указано при описании такой агрегационной функции.
Примеры:
$factory = AggregationFactory("MIN");
SELECT
AGGREGATE_BY(value, $factory) AS min_value -- применить MIN агрегацию к колонке value
FROM my_table;
AggregateTransform...
AggregateTransformInput()
преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой перед началом выполнения агрегации производится указанное преобразование входных элементов.
Аргументы:
- Фабрика для агрегационных функций;
- Лямбда функция с одним аргументом, преобразующая входной элемент.
Примеры:
$f = AggregationFactory("sum");
$g = AggregateTransformInput($f, ($x) -> (cast($x as Int32)));
$h = AggregateTransformInput($f, ($x) -> ($x * 2));
select ListAggregate([1,2,3], $f); -- 6
select ListAggregate(["1","2","3"], $g); -- 6
select ListAggregate([1,2,3], $h); -- 12
AggregateTransformOutput()
преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой после окончания выполнения агрегации производится указанное преобразование результата.
Аргументы:
- Фабрика для агрегационных функций;
- Лямбда функция с одним аргументом, преобразующая результат.
Примеры:
$f = AggregationFactory("sum");
$g = AggregateTransformOutput($f, ($x) -> ($x * 2));
select ListAggregate([1,2,3], $f); -- 6
select ListAggregate([1,2,3], $g); -- 12
AggregateFlatten
Адаптирует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory так, чтобы выполнять агрегацию над входными элементами - списками. Эта операция похожа на FLATTEN LIST BY - производится агрегация каждого элемента списка.
Аргументы:
- Фабрика для агрегационных функций.
Примеры:
$i = AggregationFactory("AGGREGATE_LIST_DISTINCT");
$j = AggregateFlatten($i);
select AggregateBy(x, $j) from (
select [1,2] as x
union all
select [2,3] as x
); -- [1, 2, 3]