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

Объединение (UNION)

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

SELECT key FROM T1
UNION
SELECT key FROM T2;

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

SELECT key FROM T1
UNION DISTINCT
SELECT key FROM T2;

Пример

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)

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

SELECT key FROM T1
UNION ALL
SELECT key FROM T2;

Пример

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)

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

SELECT key FROM T1
INTERSECT
SELECT key FROM T2;

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

SELECT key FROM T1
INTERSECT DISTINCT
SELECT key FROM T2;

Пример

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

Пересечение с дубликатами (INTERSECT ALL)

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

SELECT key FROM T1
INTERSECT ALL
SELECT key FROM T2;

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

Пример

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

Исключение (EXCEPT)

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

SELECT key FROM T1
EXCEPT
SELECT key FROM T2;

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

SELECT key FROM T1
EXCEPT DISTINCT
SELECT key FROM T2;

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

Пример

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

Исключение с дубликатами (EXCEPT ALL)

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

SELECT key FROM T1
EXCEPT ALL
SELECT key FROM T2;

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

Пример

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

Режимы "по именам" и "по позициям"

Поддерживаются два режима выполнения вышеперечисленных операций – по именам колонок (режим по умолчанию) и по позициям колонок (соответствует стандарту ANSI SQL и включается через соответствующую PRAGMA).

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

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

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

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

Пример

В результате выполнения данного запроса по умолчанию, в режиме "по именам", будет сформирована выборка с тремя колонками x, y, и z:

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:

PRAGMA PositionalUnionAll;

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

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

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...
Предыдущая