# Функции для массивов и условий

### ALL()
<!-- example all_json -->
`ALL(cond FOR var IN json.array)` применяется к JSON-массивам и возвращает 1, если условие истинно для всех элементов массива, и 0 в противном случае. `cond` — это общее выражение, которое также может использовать `var` в качестве текущего значения элемента массива внутри себя.

<!-- request ALL() with json -->
```sql
select *, ALL(x>0 AND x<4 FOR x IN j.ar) from tbl
```

<!-- response ALL() with json -->
```sql
+------+--------------+--------------------------------+
| id   | j            | all(x>0 and x<4 for x in j.ar) |
+------+--------------+--------------------------------+
|    1 | {"ar":[1,3]} |                              1 |
|    2 | {"ar":[3,7]} |                              0 |
+------+--------------+--------------------------------+
2 rows in set (0.00 sec)
```

<!-- request ALL() with json ex. 2 -->
```sql
select *, ALL(x>0 AND x<4 FOR x IN j.ar) cond from tbl where cond=1
```

<!-- response ALL() with json ex. 2 -->
```sql
+------+--------------+------+
| id   | j            | cond |
+------+--------------+------+
|    1 | {"ar":[1,3]} |    1 |
+------+--------------+------+
1 row in set (0.00 sec)
```

<!-- end -->

<!-- example all_mva -->
`ALL(mva)` — это специальный конструктор для многозначных атрибутов. При использовании с операторами сравнения (включая сравнение с `IN()`) возвращает 1, если все значения из MVA-атрибута найдены среди сравниваемых значений.

<!-- request ALL() with MVA -->
```sql
select * from tbl where all(m) >= 1
```

<!-- response ALL() with MVA -->
```sql
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)
```
<!-- request ALL() with MVA and IN() -->
```sql
select * from tbl where all(m) in (1, 3, 7, 10)
```

<!-- response ALL() with MVA and IN() -->
```sql
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)
```

<!-- end -->

<!-- example all_not_in -->
Чтобы сравнить MVA-атрибут с массивом, избегайте использования `<mva> NOT ALL()`; вместо этого используйте `ALL(<mva>) NOT IN()`.

<!-- request ALL() with MVA and NOT IN() -->
```sql
select * from tbl where all(m) not in (2, 4)
```

<!-- response ALL() with MVA and NOT IN() -->
```sql
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)
```

<!-- end -->


<!-- example all_string -->

`ALL(string list)` — это специальная операция для фильтрации строковых тегов.

Если все слова, перечисленные в качестве аргументов `ALL()`, присутствуют в атрибуте, фильтр срабатывает. Необязательный `NOT` инвертирует логику.

Этот фильтр внутренне использует покдокументное сопоставление, поэтому в случае запроса с полным сканированием он может работать медленнее, чем ожидается. Он предназначен для атрибутов, которые не индексируются, например, вычисляемых выражений или тегов в таблицах PQ. Если вам нужна такая фильтрация, рассмотрите вариант размещения строкового атрибута как полнотекстового поля с последующим использованием полнотекстового оператора `match()`, который вызовет полнотекстовый поиск.

<!-- request ALL() with strings -->
```sql
select * from tbl where tags all('bug', 'release')
```

<!-- response ALL() with strings -->
```
+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)
```

<!-- request ALL() with strings and NOT -->
```sql
mysql> select * from tbl

+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)

mysql> select * from tbl where tags not all('bug')

Empty set (0.00 sec)
```
<!-- end -->

### ANY()

<!-- example any_json -->
`ANY(cond FOR var IN json.array)` применяется к JSON-массивам и возвращает 1, если условие истинно для любого элемента массива, и 0 в противном случае. `cond` — это общее выражение, которое также может использовать `var` в качестве текущего значения элемента массива внутри себя.

<!-- request ANY() with json -->
```sql
select *, ANY(x>5 AND x<10 FOR x IN j.ar) from tbl
```

<!-- response ANY() with json -->
```sql
+------+--------------+---------------------------------+
| id   | j            | any(x>5 and x<10 for x in j.ar) |
+------+--------------+---------------------------------+
|    1 | {"ar":[1,3]} |                               0 |
|    2 | {"ar":[3,7]} |                               1 |
+------+--------------+---------------------------------+
2 rows in set (0.00 sec)
```

<!-- request ANY() with json ex. 2 -->
```sql
select *, ANY(x>5 AND x<10 FOR x IN j.ar) cond from tbl where cond=1
```

<!-- response ANY() with json ex. 2 -->
```sql
+------+--------------+------+
| id   | j            | cond |
+------+--------------+------+
|    2 | {"ar":[3,7]} |    1 |
+------+--------------+------+
1 row in set (0.00 sec)
```

<!-- end -->

<!-- example any_mva -->
`ANY(mva)` — это специальный конструктор для многозначных атрибутов. При использовании с операторами сравнения (включая сравнение с `IN()`) возвращает 1, если любое из значений MVA найдено среди сравниваемых значений.

При сравнении массива с помощью `IN()`, по умолчанию подразумевается `ANY()`, если не указано иное, но будет выдано предупреждение об отсутствующем конструкторе.

<!-- request ANY() with MVA -->
```sql
mysql> select * from tbl

+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.01 sec)

mysql> select * from tbl where any(m) > 5

+------+------+
| id   | m    |
+------+------+
|    2 | 3,7  |
+------+------+
1 row in set (0.00 sec)
```
<!-- request ANY() with MVA and IN() -->
```sql
select * from tbl where any(m) in (1, 7, 10)
```

<!-- response ANY() with MVA and IN() -->
```sql
+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)
```

<!-- end -->

<!-- example any_not_in -->
Чтобы сравнить MVA-атрибут с массивом, избегайте использования `<mva> NOT ANY()`; вместо этого используйте `<mva> NOT IN()` или `ANY(<mva>) NOT IN()`.

<!-- request ANY() with MVA and NOT IN() -->
```sql
mysql> select * from tbl

+------+------+
| id   | m    |
+------+------+
|    1 | 1,3  |
|    2 | 3,7  |
+------+------+
2 rows in set (0.00 sec)

mysql> select * from tbl where any(m) not in (1, 3, 5)

+------+------+
| id   | m    |
+------+------+
|    2 | 3,7  |
+------+------+
1 row in set (0.00 sec)
```

<!-- end -->

<!-- example any_string -->

`ANY(string list)` — это специальная операция для фильтрации строковых тегов.

Если любое из слов, перечисленных в качестве аргументов `ANY()`, присутствует в атрибуте, фильтр срабатывает. Необязательный `NOT` инвертирует логику.

Этот фильтр внутренне использует покдокументное сопоставление, поэтому в случае запроса с полным сканированием он может работать медленнее, чем ожидается. Он предназначен для атрибутов, которые не индексируются, например, вычисляемых выражений или тегов в таблицах PQ. Если вам нужна такая фильтрация, рассмотрите вариант размещения строкового атрибута как полнотекстового поля с последующим использованием полнотекстового оператора `match()`, который вызовет полнотекстовый поиск.

<!-- request ANY() with strings -->
```sql
select * from tbl where tags any('bug', 'feature')
```

<!-- response ANY() with strings -->
```
+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)
```

<!-- request ANY() with strings and NOT -->
```sql
select * from tbl
--------------

+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
|    2 | bug priority_low release  |
+------+---------------------------+
2 rows in set (0.00 sec)

--------------
select * from tbl where tags not any('feature', 'priority_low')
--------------

+------+---------------------------+
| id   | tags                      |
+------+---------------------------+
|    1 | bug priority_high release |
+------+---------------------------+
1 row in set (0.01 sec)
```


<!-- end -->

### CONTAINS()

`CONTAINS(polygon, x, y)` проверяет, находится ли точка (x,y) внутри заданного полигона, и возвращает 1, если истинно, или 0, если ложно. Полигон должен быть задан с помощью функции [POLY2D()](../Functions/Geo_spatial_functions.md#POLY2D%28%29). Первая функция предназначена для "маленьких" полигонов, то есть со стороной менее 500 км (300 миль), и она не учитывает кривизну Земли для скорости. Для больших расстояний следует использовать `GEOPOLY2D`, которая разбивает заданный полигон на меньшие части, учитывая кривизну Земли.

### IF()

<!-- example if -->
Поведение `IF()` немного отличается от его аналога в MySQL. Она принимает 3 аргумента, проверяет, равен ли первый аргумент 0.0, возвращает второй аргумент, если он не равен нулю, или третий, когда равен. Обратите внимание, что в отличие от операторов сравнения, `IF()` **не** использует порог! Поэтому безопасно использовать результаты сравнений в качестве её первого аргумента, но арифметические операторы могут давать неожиданные результаты. Например, следующие два вызова дадут *разные* результаты, хотя они логически эквивалентны:

<!-- request IF() -->
```sql
IF ( sqrt(3)*sqrt(3)-3<>0, a, b )
IF ( sqrt(3)*sqrt(3)-3, a, b )
```

<!-- end -->

В первом случае оператор сравнения <> вернёт 0.0 (ложь) из-за порога, и `IF()` всегда вернёт `**` в результате. Во втором случае то же выражение `sqrt(3)*sqrt(3)-3` будет сравниваться с нулём *без* порога самой функцией `IF()`. Однако его значение будет немного отличаться от нуля из-за ограниченной точности вычислений с плавающей запятой. Из-за этого сравнение с 0.0, выполняемое `IF()`, не пройдёт, и второй вариант вернёт 'a' в качестве результата.

### HISTOGRAM()
<!-- example histogram -->
`HISTOGRAM(expr, {hist_interval=size, hist_offset=value})` принимает размер интервала и возвращает номер интервала для значения. Ключевая функция:
```sql
key_of_the_bucket = interval + offset * floor ( ( value - offset ) / interval )
```
Аргумент гистограммы `interval` должен быть положительным. Аргумент гистограммы `offset` должен быть положительным и меньше `interval`. Используется в агрегации, `FACET` и группировке.

<!-- intro -->
Пример:

<!-- request HISTOGRAM() -->
```sql
SELECT COUNT(*),
HISTOGRAM(price, {hist_interval=100}) as price_range
FROM facets
GROUP BY price_range ORDER BY price_range ASC;
```
<!-- end -->

### IN()
`IN(expr,val1,val2,...)` принимает 2 или более аргументов и возвращает 1, если первый аргумент (expr) равен любому из остальных аргументов (val1..valN), или 0 в противном случае. В настоящее время все проверяемые значения (но не само выражение) должны быть константами. Константы предварительно сортируются, и используется бинарный поиск, поэтому `IN()` даже для большого произвольного списка констант будет очень быстрым. Первый аргумент также может быть атрибутом MVA. В этом случае `IN()` вернет 1, если любое из значений MVA равно любому из других аргументов. `IN()` также поддерживает синтаксис `IN(expr,@uservar)` для проверки, принадлежит ли значение списку в заданной глобальной пользовательской переменной. Первый аргумент может быть атрибутом JSON.

### INDEXOF()
`INDEXOF(cond FOR var IN json.array)` функция перебирает все элементы в массиве и возвращает индекс первого элемента, для которого 'cond' истинно, и -1, если 'cond' ложно для каждого элемента в массиве.

### INTERVAL()
`INTERVAL(expr,point1,point2,point3,...)` принимает 2 или более аргументов и возвращает индекс аргумента, который меньше первого аргумента: возвращает 0, если `expr<point1`, 1, если `point1<=expr<point2`, и так далее. Для корректной работы этой функции требуется, чтобы `point1<point2<...<pointN`.

### LENGTH()
`LENGTH(attr_mva)` функция возвращает количество элементов в наборе MVA. Работает как с 32-битными, так и с 64-битными атрибутами MVA. `LENGTH(attr_json)` возвращает длину поля в JSON. Возвращаемое значение зависит от типа поля. Например, `LENGTH(json_attr.some_int)` всегда возвращает 1, а `LENGTH(json_attr.some_array)` возвращает количество элементов в массиве. `LENGTH(string_expr)` функция возвращает длину строки, полученной из выражения.
[TO_STRING()](../Functions/Type_casting_functions.md#TO_STRING%28%29) должно заключать выражение, независимо от того, возвращает ли выражение не-строку или это просто строковый атрибут.

### RANGE()
<!-- example range -->
`RANGE(expr, {range_from=value,range_to=value})` принимает набор диапазонов и возвращает номер интервала для значения.
Это выражение включает значение `range_from` и исключает значение `range_to` для каждого диапазона. Диапазон может быть открытым — иметь только значение `range_from` или только значение `range_to`. Используется в агрегации, `FACET` и группировке.

<!-- intro -->
Пример:

<!-- request RANGE() -->
```sql
SELECT COUNT(*),
RANGE(price, {range_to=150},{range_from=150,range_to=300},{range_from=300}) price_range
FROM facets
GROUP BY price_range ORDER BY price_range ASC;
```
<!-- end -->

### REMAP()
<!-- example remap -->
`REMAP(condition, expression, (cond1, cond2, ...), (expr1, expr2, ...))` функция позволяет делать исключения для значений выражения в зависимости от значений условия. Выражение условия всегда должно давать целое число, в то время как выражение может давать целое число или число с плавающей точкой.

<!-- intro -->
Пример:

<!-- request REMAP() -->
```sql
SELECT id, size, REMAP(size, 15, (5,6,7,8), (1,1,2,2)) s
FROM products
ORDER BY s ASC;
```
<!-- request Another example -->
```sql
SELECT REMAP(userid, karmapoints, (1, 67), (999, 0)) FROM users;
SELECT REMAP(id%10, salary, (0), (0.0)) FROM employes;
```
<!-- end -->

Это поместит документы с размерами 5 и 6 первыми, за ними последуют размеры 7 и 8. В случае, если есть исходное значение, не указанное в массиве (например, размер 10), оно по умолчанию будет равно 15 и, в данном случае, будет помещено в конец.


<!-- proofread -->

