---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://ytsaurus.tech/docs/en/yql/syntax/select/operators.md
  - https://ytsaurus.tech/docs/ru/yql/syntax/select/operators.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ytsaurus.tech/docs/ru/llms.txt

# Операции с результатами подзапросов: UNION, INTERSECT, EXCEPT

## Объединение (UNION) {#union}

Объединение результатов нескольких `SELECT` (или подзапросов) с удалением дубликатов.
Поведение идентично последовательному исполнению `UNION ALL` и `SELECT DISTINCT *`.
См. [UNION ALL](#union-all) для информации о деталях поведения.

```yql
SELECT key FROM T1
UNION
SELECT key FROM T2;
```

Также допускается явное указание ключевого слова `DISTINCT`, которое не влияет на результат выполнения.

```yql
SELECT key FROM T1
UNION DISTINCT
SELECT key FROM T2;
```

#### Пример

```yql
SELECT * FROM (VALUES (1, 2)) AS t(x, y)
UNION
SELECT * FROM (VALUES (1, 2)) AS t(x, y);
```
```
x	y
1	2
```

## Объединение c дубликатами (UNION ALL) {#union-all}

Объединение результатов нескольких `SELECT` (или подзапросов) без удаления дубликатов.

```yql
SELECT key FROM T1
UNION ALL
SELECT key FROM T2;
```

#### Пример

```yql
SELECT * FROM (VALUES (1, 2)) AS t(x, y)
UNION ALL
SELECT * FROM (VALUES (1, 2)) AS t(x, y);
```
```
x	y
1	2
1	2
```

## Пересечение (INTERSECT) {#intersect}

Пересечение результатов двух `SELECT` (или подзапросов) с удалением дубликатов.
Поведение идентично последовательному исполнению `INTERSECT ALL` и `SELECT DISTINCT *`.
См. [INTERSECT ALL](#intersect-all) для информации о деталях поведения.

```yql
SELECT key FROM T1
INTERSECT
SELECT key FROM T2;
```

Также допускается явное указание ключевого слова `DISTINCT`, которое не влияет на результат выполнения.

```yql
SELECT key FROM T1
INTERSECT DISTINCT
SELECT key FROM T2;
```

#### Пример

```yql
SELECT * FROM (VALUES (1), (1), (1), (2)) AS t(x)
INTERSECT
SELECT * FROM (VALUES (1), (1)) AS t(x);
```
```
x
1
```

## Пересечение с дубликатами (INTERSECT ALL) {#intersect-all}

Пересечение результатов двух `SELECT` (или подзапросов) без удаления дубликатов.

```yql
SELECT key FROM T1
INTERSECT ALL
SELECT key FROM T2;
```

Результатом запроса является таблица дублирующихся строк, лежащих в обеих исходных таблицах.
Количество дубликатов строк равно минимуму из вхождений в каждую из исходных таблиц.

#### Пример

```yql
SELECT * FROM (VALUES (1), (1), (1), (2)) AS t(x)
INTERSECT ALL
SELECT * FROM (VALUES (1), (1)) AS t(x);
```
```
x
1
1
```

## Исключение (EXCEPT) {#except}

Исключение результатов одного `SELECT` (или подзапроса) из результатов другого.

```yql
SELECT key FROM T1
EXCEPT
SELECT key FROM T2;
```

Также допускается явное указание ключевого слова `DISTINCT`, которое не влияет на результат выполнения.

```yql
SELECT key FROM T1
EXCEPT DISTINCT
SELECT key FROM T2;
```

Результатом запроса является таблица уникальных строк, лежащих в первой исходной таблице и не лежащих во второй.

#### Пример

```yql
SELECT * FROM (VALUES (1), (1), (1), (2)) AS t(x)
EXCEPT
SELECT * FROM (VALUES (1)) AS t(x);
```
```
x
2
```

## Исключение с дубликатами (EXCEPT ALL) {#except-all}

Исключение результатов одного `SELECT` (или подзапроса) из результатов другого с учётом дубликатов (количества вхождений).

```yql
SELECT key FROM T1
EXCEPT ALL
SELECT key FROM T2;
```

Результатом запроса является таблица дублирующихся строк, которые встречаются в первой таблице чаще, чем во второй.
Количество дубликатов строк равно разности количества вхождений в первую и количества вхождений во вторую.

#### Пример

```yql
SELECT * FROM (VALUES (1), (1), (1), (2)) AS t(x)
EXCEPT ALL
SELECT * FROM (VALUES (1)) AS t(x);
```
```
x
2
1
1
```

## Режимы "по именам" и "по позициям" {#positional-mode}

Поддерживаются два режима выполнения вышеперечисленных операций – по именам колонок (режим по умолчанию) и по позициям колонок (соответствует стандарту ANSI SQL и включается через соответствующую [PRAGMA](https://ytsaurus.tech/docs/ru/yql/syntax/pragma/global.md#positionalunionall)).

### По именам колонок

В режиме "по именам" результирующая схема данных выводится по следующим правилам:

* в результирующую таблицу включаются все колонки, которые встречались хоть в одной из входных таблиц;
* если колонка присутствовала не во всех входных таблицах, то ей автоматически присваивается [опциональный тип данных](https://ytsaurus.tech/docs/ru/yql/types/optional.md) (допускающий значение `NULL`);
* если колонка в разных входных таблицах имела разные типы, то выводится общий тип (наиболее широкий);
* если колонка в разных входных таблицах имела разнородный тип, например строку и число, то это считается ошибкой.

Порядок выходных колонок в этом режиме выводится как наибольший общий префикс порядка входов, после чего следуют все остальные колонки в алфавитном порядке.
Если наибольший общий префикс пуст (в том числе и из-за отсутствия порядка на одном из входов), то порядок выхода не определен.

#### Пример

В результате выполнения данного запроса по умолчанию, в режиме "по именам", будет сформирована выборка с тремя колонками `x`, `y`, и `z`:
```yql
SELECT 1 AS x
UNION ALL
SELECT 2 AS y
UNION ALL
SELECT 3 AS z;
```
```
x	y	z
1
	2
		3
```

### По позициям колонок

В режиме "по позициям" результирующая схема данных выводится по следующим правилам:

* число колонок во всех входах должно быть одинаковым;
* порядок колонок во всех входах должен быть определен;
* имена результирующих колонок совпадают с именами колонок первой таблицы;
* тип результирующих колонок выводится как общий (наиболее широкий) тип из типов входных колонок стоящих на одинаковых позициях.

Порядок выходных колонок в этом режиме совпадает с порядком колонок первого входа.

#### Пример

При включенной `PRAGMA PositionalUnionAll;` в следующем запросе результатом будет одна колонка `x`:
```yql
PRAGMA PositionalUnionAll;

SELECT 1 AS x
UNION ALL
SELECT 2 AS y
UNION ALL
SELECT 3 AS z;
```
```
x
1
2
3
```

Если порядок колонок не определён (например, при использовании `AS_TABLE`), запрос завершается с ошибкой:
```yql
PRAGMA PositionalUnionAll;

SELECT 1 AS x, 2 as y
UNION ALL
SELECT * FROM AS_TABLE([<|x:3, y:4|>]);
```
```
Input #1 does not have ordered columns...
```
