提交 afd57d03 编写于 作者: B BayoNet

- Functions with special support for NULL

- Descriptions for functons: arrayResize, multiIf, getSizeOfEnumType, toColumnTypeName, dumpColumnStructure, defaultValueOfArgumentType, indexHint, replicate.
- Enum description is updated
上级 c31dca2c
<a name="data_type-enum"></a>
# Enum
Enum8 или Enum16. Представляет собой конечное множество строковых значений, сохраняемых более эффективно, чем это делает тип данных `String`.
Семейство типов. Включает в себя типы `Enum8` и `Enum16`. `Enum` сохраняет конечный набор пар `'строка' = целое число`. Все операции с данными типа `Enum` ClickHouse выполняет как с числами, однако пользователь при этом работает со строковыми константами. Это более эффективно с точки зрения производительности, чем работа с типом данных `String`.
Подтипы:
- `Enum8` состоит из пар `'String' = Int8`.
- `Enum16` состоит из пар `'String' = Int16`.
## Примеры применения
Создадим таблицу со столбцом типа `Enum8('hello' = 1, 'world' = 2)`.
```
CREATE TABLE t_enum
(
x Enum8('hello' = 1, 'world' = 2)
)
ENGINE = TinyLog
```
В столбец `x` можно сохранять только значения, перечисленные при определении типа, т.е. `'hello'` или `'world'`. Если попытаться сохранить другое значение, ClickHouse сгенерирует исключение.
```
:) INSERT INTO t_enum Values('hello'),('world'),('hello')
INSERT INTO t_enum VALUES
Ok.
3 rows in set. Elapsed: 0.002 sec.
:) insert into t_enum values('a')
Пример:
INSERT INTO t_enum VALUES
```text
Enum8('hello' = 1, 'world' = 2)
Exception on client:
Code: 49. DB::Exception: Unknown element 'a' for type Enum8('hello' = 1, 'world' = 2)
```
- тип данных с двумя возможными значениями - 'hello' и 'world'.
При запросе данных из таблицы ClickHouse выдаст строковые значения из `Enum`.
```
SELECT * FROM t_enum
┌─x─────┐
│ hello │
│ world │
│ hello │
└───────┘
```
Если необходимо увидеть цифровые эквиваленты строкам, то необходимо привести тип.
```
SELECT CAST(x, 'Int8') FROM t_enum
┌─CAST(x, 'Int8')─┐
│ 1 │
│ 2 │
│ 1 │
└─────────────────┘
```
Чтобы создать значение типа Enum в запросе, также необходима функция `CAST`.
```
SELECT toTypeName(CAST('a', 'Enum8(\'a\' = 1, \'b\' = 2)'))
┌─toTypeName(CAST('a', 'Enum8(\'a\' = 1, \'b\' = 2)'))─┐
│ Enum8('a' = 1, 'b' = 2) │
└──────────────────────────────────────────────────────┘
```
## Общие правила и особенности использования
Для каждого из значений прописывается число в диапазоне `-128 .. 127` для `Enum8` или в диапазоне `-32768 .. 32767` для `Enum16`. Все строки должны быть разными, числа - тоже. Разрешена пустая строка. При указании такого типа (в определении таблицы), числа могут идти не подряд и в произвольном порядке. При этом, порядок не имеет значения.
В оперативке столбец такого типа представлен так же, как `Int8` или `Int16` соответствующими числовыми значениями.
Ни строка, ни цифровое значение в `Enum` не могут быть [NULL](../query_language/syntax.md#null-literal).
`Enum` может быть передан в тип [Nullable](nullable.md#data_type-nullable). Таким образом, если создать таблицу запросом
```
CREATE TABLE t_enum_nullable
(
x Nullable( Enum8('hello' = 1, 'world' = 2) )
)
ENGINE = TinyLog
```
, то в ней можно будет хранить не только `'hello'` и `'world'`, но и `NULL`.
```
INSERT INTO t_enum_null Values('hello'),('world'),(NULL)
```
В оперативке столбец типа `Enum` представлен так же, как `Int8` или `Int16` соответствующими числовыми значениями.
При чтении в текстовом виде, парсит значение как строку и ищет соответствующую строку из множества значений Enum-а. Если не находит - кидается исключение.
При записи в текстовом виде, записывает значение как соответствующую строку. Если в данных столбца есть мусор - числа не из допустимого множества, то кидается исключение. При чтении и записи в бинарном виде, оно осуществляется так же, как для типов данных Int8, Int16.
Неявное значение по умолчанию - это значение с минимальным номером.
......
......@@ -75,11 +75,48 @@ n должен быть любым целочисленным типом.
Проверяет наличие элемента elem в массиве arr.
Возвращает 0, если элемента в массиве нет, или 1, если есть.
`NULL` обрабатывается как значение.
```
SELECT has([1, 2, NULL], NULL)
┌─has([1, 2, NULL], NULL)─┐
│ 1 │
└─────────────────────────┘
```
## indexOf(arr, x)
Возвращает индекс элемента x (начиная с 1), если он есть в массиве, или 0, если его нет.
Возвращает индекс первого элемента x (начиная с 1), если он есть в массиве, или 0, если его нет.
Пример:
```
:) select indexOf([1,3,NULL,NULL],NULL)
SELECT indexOf([1, 3, NULL, NULL], NULL)
┌─indexOf([1, 3, NULL, NULL], NULL)─┐
│ 3 │
└───────────────────────────────────┘
```
Элементы, равные `NULL`, обрабатываются как обычные значения.
## countEqual(arr, x)
Возвращает количество элементов массива, равных x. Эквивалентно arrayCount(elem -&gt; elem = x, arr).
Возвращает количество элементов массива, равных x. Эквивалентно arrayCount(elem -> elem = x, arr).
Элементы `NULL` обрабатываются как отдельные значения.
Пример:
```
SELECT countEqual([1, 2, NULL, NULL], NULL)
┌─countEqual([1, 2, NULL, NULL], NULL)─┐
│ 2 │
└──────────────────────────────────────┘
```
## arrayEnumerate(arr)
Возвращает массив \[1, 2, 3, ..., length(arr)\]
......@@ -232,7 +269,7 @@ arrayPushBack(array, single_value)
**Аргументы**
- `array` - Массив.
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)".
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)". Может быть равно `NULL`. Функция добавит элемент `NULL` в массив, а тип элементов массива преобразует в `Nullable`.
**Пример**
......@@ -245,6 +282,8 @@ SELECT arrayPushBack(['a'], 'b') AS res
└───────────┘
```
## arrayPushFront
Добавляет один элемент в начало массива.
......@@ -256,7 +295,7 @@ arrayPushFront(array, single_value)
**Аргументы**
- `array` - Массив.
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)".
- `single_value` - Одиночное значение. В массив с числам можно добавить только числа, в массив со строками только строки. При добавлении чисел ClickHouse автоматически приводит тип `single_value` к типу данных массива. Подробнее о типах данных в ClickHouse читайте в разделе "[Типы данных](../data_types/index.md#data_types)". Может быть равно `NULL`. Функция добавит элемент `NULL` в массив, а тип элементов массива преобразует в `Nullable`.
**Пример**
......@@ -269,6 +308,43 @@ SELECT arrayPushBack(['b'], 'a') AS res
└───────────┘
```
## arrayResize
Изменяет длину массива.
```
arrayResize(array, size[, extender])
```
**Параметры:**
- `array` — массив.
- `size` — необходимая длина массива.
- Если `size` меньше изначального размера массива, то массив обрезается справа.
- Если `size` больше изначального размера массива, массив дополняется справа значениями `extender` или значениями по умолчанию для типа данных элементов массива.
- `extender` — значение для дополнения массива. Может быть `NULL`.
**Возвращаемое значение:**
Массив длины `size`.
**Примеры вызовов**
```
SELECT arrayResize([1], 3)
┌─arrayResize([1], 3)─┐
│ [1,0,0] │
└─────────────────────┘
```
```
SELECT arrayResize([1], 3, NULL)
┌─arrayResize([1], 3, NULL)─┐
│ [1,NULL,NULL] │
└───────────────────────────┘
```
## arraySlice
Возвращает срез массива.
......@@ -286,14 +362,15 @@ arraySlice(array, offset[, length])
**Пример**
```sql
SELECT arraySlice([1, 2, 3, 4, 5], 2, 3) AS res
SELECT arraySlice([1, 2, NULL, 4, 5], 2, 3) AS res
```
```
┌─res─────┐
│ [2,3,4] │
└─────────┘
┌─res────────
│ [2,NULL,4] │
└────────────
```
Элементы массива равные `NULL` обрабатываются как обычные значения.
## arrayUniq(arr, ...)
Если передан один аргумент, считает количество разных элементов в массиве.
......@@ -303,4 +380,3 @@ SELECT arraySlice([1, 2, 3, 4, 5], 2, 3) AS res
## arrayJoin(arr)
Особенная функция. Смотрите раздел ["Функция arrayJoin"](array_join.md#functions_arrayjoin).
# Условные функции
## if(cond, then, else), оператор cond ? then : else
Возвращает then, если cond != 0 или else, если cond = 0.
cond должно иметь тип UInt8, а then и else должны иметь тип, для которого есть наименьший общий тип.
Возвращает `then`, если `cond != 0` или `else`, если `cond = 0`.
`cond` должно иметь тип `UInt8`, а `then` и `else` должны иметь тип, для которого есть наименьший общий тип.
`then` и `else` могут быть `NULL`
## multiIf
Позволяет более компактно записать оператор [CASE](../operators/index.html#operator_case) в запросе.
```
multiIf(cond_1, then_1, cond_2, then_2...else)
```
**Параметры**
- `cond_N` — Условие, при выполнении которого функция вернёт `then_N`.
- `then_N` — Результат функции при выполнении.
- `else` — Результат функции, если ни одно из условий не выполнено.
Функция принимает `2N+1` параметров.
**Возвращаемые значения**
Функция возвращает одно из значений `then_N` или `else`, в зависимости от условий `cond_N`.
**Пример**
Рассмотрим таблицу
```
┌─x─┬────y─┐
│ 1 │ ᴺᵁᴸᴸ │
│ 2 │ 3 │
└───┴──────┘
```
Выполним запрос `SELECT multiIf(isNull(y), x, y < 3, y, NULL) FROM t_null`. Результат:
```
┌─multiIf(isNull(y), x, less(y, 3), y, NULL)─┐
│ 1 │
│ ᴺᵁᴸᴸ │
└────────────────────────────────────────────┘
```
......@@ -7,9 +7,21 @@
Вычисляет приблизительную ширину при выводе значения в текстовом (tab-separated) виде на консоль.
Функция используется системой для реализации Pretty форматов.
`NULL` представляется как строка, соответствующая отображению `NULL` в форматах `Pretty`.
```
SELECT visibleWidth(NULL)
┌─visibleWidth(NULL)─┐
│ 4 │
└────────────────────┘
```
## toTypeName(x)
Возвращает строку, содержащую имя типа переданного аргумента.
Если на вход функции передать `NULL`, то она вернёт тип `Nullable(Nothing)`, что соответствует внутреннему представлению `NULL` в ClickHouse.
## blockSize()
Получить размер блока.
В ClickHouse выполнение запроса всегда идёт по блокам (наборам кусочков столбцов). Функция позволяет получить размер блока, для которого её вызвали.
......@@ -19,7 +31,7 @@
В ClickHouse полноценные столбцы и константы представлены в памяти по-разному. Функции по-разному работают для аргументов-констант и обычных аргументов (выполняется разный код), хотя результат почти всегда должен быть одинаковым. Эта функция предназначена для отладки такого поведения.
## ignore(...)
Принимает любые аргументы, всегда возвращает 0.
Принимает любые аргументы, в т.ч. `NULL`, всегда возвращает 0.
При этом, аргумент всё равно вычисляется. Это может использоваться для бенчмарков.
## sleep(seconds)
......@@ -261,3 +273,270 @@ FROM
## MACStringToOUI(s)
Принимает MAC адрес в формате AA:BB:CC:DD:EE:FF (числа в шестнадцатеричной форме через двоеточие). Возвращает первые три октета как число в формате UInt64. Если MAC адрес в неправильном формате, то возвращает 0.
## getSizeOfEnumType
Возвращает количество полей в [Enum](../data_types/enum.md#data_type-enum).
```
getSizeOfEnumType(value)
```
**Параметры**
- `value` — Значение типа `Enum`.
**Возвращаемые значения**
- Количество полей входного значения типа `Enum`.
- Исключение, если тип не `Enum`.
**Пример**
```
SELECT getSizeOfEnumType( CAST('a' AS Enum8('a' = 1, 'b' = 2) ) ) AS x
┌─x─┐
│ 2 │
└───┘
```
## toColumnTypeName
Возвращает имя класса, которым представлен тип данных столбца в оперативной памяти.
```
toColumnTypeName(value)
```
**Параметры**
- `value` — Значение произвольного типа.
**Возвращаемые значения**
- Строка с именем класса, который используется для представления типа данных `value` в оперативной памяти.
**Пример разницы между `toTypeName` и `toColumnTypeName`**
```
:) select toTypeName(cast('2018-01-01 01:02:03' AS DateTime))
SELECT toTypeName(CAST('2018-01-01 01:02:03', 'DateTime'))
┌─toTypeName(CAST('2018-01-01 01:02:03', 'DateTime'))─┐
│ DateTime │
└─────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.008 sec.
:) select toColumnTypeName(cast('2018-01-01 01:02:03' AS DateTime))
SELECT toColumnTypeName(CAST('2018-01-01 01:02:03', 'DateTime'))
┌─toColumnTypeName(CAST('2018-01-01 01:02:03', 'DateTime'))─┐
│ Const(UInt32) │
└───────────────────────────────────────────────────────────┘
```
В этом примере хорошо видно, что тип данных `DateTime` хранится в памяти как `Const(UInt32)`.
## dumpColumnStructure
Выводит развернутое описание структур данных в оперативной памяти
```
dumpColumnStructure(value)
```
**Параметры**
- `value` — Значение произвольного типа.
**Возвращаемые значения**
- Строка с описанием структуры, которая используется для представления типа данных `value` в оперативной памяти.
**Пример**
```
SELECT dumpColumnStructure(CAST('2018-01-01 01:02:03', 'DateTime'))
┌─dumpColumnStructure(CAST('2018-01-01 01:02:03', 'DateTime'))─┐
│ DateTime, Const(size = 1, UInt32(size = 1)) │
└──────────────────────────────────────────────────────────────┘
```
## defaultValueOfArgumentType
Выводит значение по умолчанию для типа данных.
Не учитывает значения по умолчанию для столбцов, заданные пользователем.
```
defaultValueOfArgumentType(expression)
```
**Параметры**
- `expression` — Значение произвольного типа или выражение, результатом которого является значение произвольного типа.
**Возвращаемые значения**
- `0` для чисел;
- Пустая строка для строк;
- `ᴺᵁᴸᴸ` для [Nullable](../data_types/nullable.md#data_type-nullable).
**Пример**
```
:) SELECT defaultValueOfArgumentType( CAST(1 AS Int8) )
SELECT defaultValueOfArgumentType(CAST(1, 'Int8'))
┌─defaultValueOfArgumentType(CAST(1, 'Int8'))─┐
│ 0 │
└─────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.002 sec.
:) SELECT defaultValueOfArgumentType( CAST(1 AS Nullable(Int8) ) )
SELECT defaultValueOfArgumentType(CAST(1, 'Nullable(Int8)'))
┌─defaultValueOfArgumentType(CAST(1, 'Nullable(Int8)'))─┐
│ ᴺᵁᴸᴸ │
└───────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.002 sec.
```
## indexHint
Выводит данные, попавшие в диапазон, выбранный по индексу без фильтрации по указанному в качестве аргумента выражению.
Переданное в функцию выражение не вычисляется, но при этом ClickHouse применяет к этому выражению индекс таким же образом, как если бы выражение участвовало в запросе без `indexHint`.
**Возвращаемое значение**
- 1.
**Пример**
Рассмотрим таблицу с тестовыми данными [ontime](../getting_started/example_datasets/ontime.md#example_datasets-ontime).
```
SELECT count() FROM ontime
┌─count()─┐
│ 4276457 │
└─────────┘
```
В таблице есть индексы по полям `(FlightDate, (Year, FlightDate))`.
Выполним выборку по дате следующим образом:
```
:) SELECT FlightDate AS k, count() FROM ontime GROUP BY k ORDER BY k
SELECT
FlightDate AS k,
count()
FROM ontime
GROUP BY k
ORDER BY k ASC
┌──────────k─┬─count()─┐
│ 2017-01-01 │ 13970 │
│ 2017-01-02 │ 15882 │
........................
│ 2017-09-28 │ 16411 │
│ 2017-09-29 │ 16384 │
│ 2017-09-30 │ 12520 │
└────────────┴─────────┘
273 rows in set. Elapsed: 0.072 sec. Processed 4.28 million rows, 8.55 MB (59.00 million rows/s., 118.01 MB/s.)
```
В этой выборке индекс не используется и ClickHouse обработал всю таблицу (`Processed 4.28 million rows`). Для подключения индекса выберем конкретную дату и выполним следующий запрос:
```
:) SELECT FlightDate AS k, count() FROM ontime WHERE k = '2017-09-15' GROUP BY k ORDER BY k
SELECT
FlightDate AS k,
count()
FROM ontime
WHERE k = '2017-09-15'
GROUP BY k
ORDER BY k ASC
┌──────────k─┬─count()─┐
│ 2017-09-15 │ 16428 │
└────────────┴─────────┘
1 rows in set. Elapsed: 0.014 sec. Processed 32.74 thousand rows, 65.49 KB (2.31 million rows/s., 4.63 MB/s.)
```
В последней строке выдачи видно, что благодаря использованию индекса, ClickHouse обработал значительно меньшее количество строк (`Processed 32.74 thousand rows`).
Теперь передадим выражение `k = '2017-09-15'` в функцию `indexHint`:
```
:) SELECT FlightDate AS k, count() FROM ontime WHERE indexHint(k = '2017-09-15') GROUP BY k ORDER BY k
SELECT
FlightDate AS k,
count()
FROM ontime
WHERE indexHint(k = '2017-09-15')
GROUP BY k
ORDER BY k ASC
┌──────────k─┬─count()─┐
│ 2017-09-14 │ 7071 │
│ 2017-09-15 │ 16428 │
│ 2017-09-16 │ 1077 │
│ 2017-09-30 │ 8167 │
└────────────┴─────────┘
4 rows in set. Elapsed: 0.004 sec. Processed 32.74 thousand rows, 65.49 KB (8.97 million rows/s., 17.94 MB/s.)
```
В ответе на запрос видно, что ClickHouse применил индекс таким же образом, что и в предыдущий раз (`Processed 32.74 thousand rows`). Однако по результирующему набору строк видно, что выражение `k = '2017-09-15'` не использовалось при формировании результата.
Поскольку индекс в ClickHouse разреженный, то при чтении диапазона в ответ попадают "лишние" данные, в данном случае соседние даты. Функция `indexHint` позволяет их увидеть.
## replicate
Создает массив, заполненный одним значением.
Используется для внутренней реализации [arrayJoin](array_join.md#functions_arrayjoin).
```
replicate(x, arr)
```
**Параметры**
- `arr` — Исходный массив. ClickHouse создаёт новый массив такой же длины как исходный и заполняет его значением `x`.
- `x` — Значение, которым будет заполнен результирующий массив.
**Выходное значение**
- Массив, заполненный значением `x`.
**Пример**
```
SELECT replicate(1, ['a', 'b', 'c'])
┌─replicate(1, ['a', 'b', 'c'])─┐
│ [1,1,1] │
└───────────────────────────────┘
```
......@@ -113,3 +113,21 @@ SELECT
```
Преобразование в FixedString(N) работает только для аргументов типа String или FixedString(N).
Поддержано преобразование к типу [Nullable](../data_types/nullable.md#data_type-nullable) и обратно. Пример:
```
SELECT toTypeName(x) FROM t_null
┌─toTypeName(x)─┐
│ Int8 │
│ Int8 │
└───────────────┘
SELECT toTypeName(CAST(x, 'Nullable(UInt16)')) FROM t_null
┌─toTypeName(CAST(x, 'Nullable(UInt16)'))─┐
│ Nullable(UInt16) │
│ Nullable(UInt16) │
└─────────────────────────────────────────┘
```
......@@ -83,6 +83,8 @@
Условный оператор сначала вычисляет значения b и c, затем проверяет выполнение условия a, и только после этого возвращает соответствующее значение. Если в качестве b или с выступает функция arrayJoin(), то размножение каждой строки произойдет вне зависимости от условия а.
<a name="operator_case"><a>
## Условное выражение
```sql
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册