Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 2. SQL. Объединения, подзапросы..docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
35.63 Кб
Скачать

Оператор exists

Операторы EXISTS и NOT EXISTS не сравнивают значения, а проверяют, вернул ли подзапрос хотя бы одну строку или нет.

Основные параметры такой проверки:

1) тест на наличие строк в результате выполнения подзапроса не сравнивает значения, поэтому не сопровождается оператором сравнения;

2) запрос может быть простым или сложным, но обычно он сложный;

3) запрос может считать любое количество столбцов и строк;

4) предложение SELECT в подзапросе задается как SELECT * для считывания всех столбцов. Нет необходимости указывать отдельные названия столбцов, так как EXISTS просто проверяет наличие строк, которые соответствуют условию запроса; сами значения в строках не рассматриваются;

5) если запрос считывает хотя бы одну строку, тест на EXISTS становится истинным, а тест на NOT EXISTS – ложным;

6) если запрос не считывает строки, тест на NOT EXISTS становится истинным, а тест на EXISTS – ложным;

7) строка запроса, содержащая во всех полях NULL, все равно считается строкой (тест на EXISTS становится истинным, а тест на NOT EXISTS – ложным).

Выполнение теста на наличие выборки

WHERE [NOT] EXISTS (subquery)

subquery – это запрос, который считывает любое количество столбцов и строк.

Если запрос считывает хотя бы одну строку, условие EXISTS задается как истинное. Если запрос считывает пустые строки, условие EXISTS задается как ложное.

Чтобы изменить результат тестирования, необходимо указать NOT.

Предложение HAVING имеет такую же структуру:

HAVING [NOT] EXISTS (subquery)

Примеры

1) Отобразить список всех издательств, которые опубликовали биографии

SELECT pub_name

FROM publishers p

WHERE EXISTS

(SELECT *

FROM titles t

WHERE t.pub_id = p.pub_id

AND type = 'biography');

2) Отобразить список авторов, которые не написали ни одной книги (в том числе в соавторстве).

SELECT au_id, au_fname, au_lname

FROM authors a

WHERE NOT EXISTS

(SELECT *

FROM title_authors ta

WHERE ta.au_id = a.au_id);

3) Отобразить список авторов, которые живут в городе, где расположено издательство

SELECT au_id, au_lname, au_fname, city

FROM authors a

WHERE EXISTS

(SELECT *

FROM publishers p

WHERE p.city = a.city);

Можно также использовать функцию COUNT(*), чтобы определить, считывает ли запрос хотя бы одну строку. COUNT(*), как правило, не так эффективна, как EXISTS. СУБД перестает обрабатывать запрос EXISTS тогда, когда определит, что он считывает хотя бы одну строку. В то же время COUNT(*) заставляет СУБД обработать весь запрос.

Запрос аналогичен запросу 3, но работает медленнее.

SELECT au_id, au_lname, au_fname, city

FROM authors a

WHERE

(SELECT COUNT(*)

FROM publishers p

WHERE p.city = a.city) > 0;

Операторы для работы с несколькими запросами

1.UNION

Иногда требуется как-то работать с несколькими результатами запросов.

Комбинировать строки можно с помощью операторов UNION, INTERSECT и EXCEPT. Данные операторы предназначены для преобразования двух команд SELECT в единый результат. Можно смешивать эти операторы так, чтобы комбинировать несколько таблиц, а не только две. Оператор UNION из перечисленных используется чаще всего.

Оператор UNION комбинирует результаты двух запросов в один результат, который объединяет строки, считанные двумя запросами. Выражение UNION удаляет из результата посторяющиеся строки, выражение UNION ALL сохраняет повторы. Операторы UNION просты, но имеют ряд ограничений:

1) списки столбцов команды SELECT в двух запросах должны включать одинаковое число столбцов;

2) соответствующие столбцы в двух запросах должны быть заданы в одинаковом порядке;

3) если имена соответствующих столбцов совпадает, то их название будет использовано в результате. Если названия соответствующих столбцов различаются, то СУБД самостоятельно определит имя столбца в результате. Большинство СУБД заимствуют названия столбцов для результата из первого отдельного запроса в команде UNION

4) предложения GROUP BY и HAVING можно задавать только в отдельных запросах, их нельзя использовать для изменения конечного результата

5) предложение ORDER BY может использоваться только в последнем запросе команды UNION. Эта сортировка применяется к конечному результату после комбинирования. Так как названия столбцов в итоге различаются для разных СУБД, для указания порядка сортировки проще всего использовать относительные положения столбцов. То есть вместо названия столбца можно указывать порядковый номер этого столбца.

Комбинирование строк

select_statement1

UNION [ALL]

select_statement2

select_statement1 и select_statement2 - команды SELECT. Необходимо задать количество и порядок столбцов для двух команд, а тип данных в соответствующих столбцах должен быть совместимым. Если опция ALL не задается, то повторяющиеся строки будут удалены из результата.

Примеры:

1) отобразить список городов, в которых живут авторы и находятся издательства.

SELECT city FROM authors

UNION

SELECT city FROM publishers

По умолчанию UNION удаляет из результата повторяющиеся строки.

2) Отобразить список фамилий авторов и названий издательств из города Москва, указав тип, то есть нужно указать, автор это или издательство. Отсортировать по названию/имени.

SELECT 'author' AS "Type",

lname,

city

FROM authors

WHERE city='Moscow'

UNION

SELECT 'publisher',

name,

city

FROM publishers

WHERE city='Moscow'

ORDER BY 1 ASC

UNION является коммутативной командой: A UNION B - это то же самое, что B UNION A.

Для объединения в одной команде UNION и UNION ALL следует пользоваться круглыми скобками, чтобы задать порядок расчетов.

SELECT * FROM table1

UNION ALL

(

SELECT * FROM table2

UNION

SELECT * FROM table3

)

и

(

SELECT * FROM table1

UNION ALL

SELECT * FROM table2

)

UNION

SELECT * FROM table3

Первая команда удаляет повторы в объединении table2 и table3, но не удаляет их в результате и table1. Вторая команда сохраняет повторы в объединении table1 и table2, но удаляет их в последующем объединении с table3, поэтому ALL не влияет на конечный результат команды.

2. INTERSECT

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

Поиск общих строк

select_statement1

INTERSECT

select_statement2

select_statement1 и select_statement2 - команды SELECT. Необходимо задать количество и порядок столбцов для двух команд, а тип данных в соответствующих столбцах должен быть совместимым. Повторяющиеся строки будут удалены из результата.

INTERSECT является коммутативной командой: A INTERSECT B – это то же самое, что B INTERSECT A.

В SQL у INTERSECT более высокий приоритет по сравнению с UNION и EXCEPT, но в конкретной СУБД приоритеты могут быть другими. Чтобы задать порядок расчета в запросах со смешанными операторами, стоит пользоваться круглыми скобками.

Очень полезно воспринимать UNION как логический вариант OR, а INTERSECT - как логический вариант AND. Например, если нужно узнать, какие товары поставляются продавцов A и B.

SELECT product_id

FROM vendor_a_product_list

UNION

SELECT product_id

FROM vendor_b_product_list

Если нужно узнать, какие товары поставляются и продавцом A, и продавцом B, то:

SELECT product_id

FROM vendor_a_product_list

INTERSECT

SELECT product_id

FROM vendor_b_product_list

Microsoft Access, Microsoft SQL Server и MySQL не поддерживают команду INTERSECT. Её можно переписать с использованием INNER JOIN или с использованием предложения EXISTS.

SELECT DISTINCT authors.city

FROM authors

INNER JOIN publishers

ON authors.city = publishers.city

SELECT DISTINCT city

FROM authors

WHERE EXISTS

(SELECT *

FROM publishers

WHERE authors.city = publishers.city)

3. EXCEPT

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

Поиск разных строк

select_statement1

EXCEPT

select_statement2

select_statement1 и select_statement2 - команды SELECT. Необходимо задать количество и порядок столбцов для двух команд, а тип данных в соответствующих столбцах должен быть совместимым. Повторяющиеся строки будут удалены из результата.

В отличие от команд UNION и INTERSECT, команда EXCEPT не является коммутативной:

A EXCEPT B – это не то же самое, что B EXCEPT A.

Отобразить список городов, в которых живут авторы, но нет издательств.

SELECT city FROM authors

EXCEPT

SELECT city FROM publishers

Microsoft Access, Microsoft SQL Server и MySQL не поддерживают команду INTERSECT.

Её можно переписать с использованием внешнего запроса или с использованием предложения NOT EXISTS или NOT IN.

SELECT DISTINCT a.city

FROM authors a

LEFT OUTER JOIN publishers p

ON a.city = p.city

WHERE p.city IS NULL

или

SELECT DISTINCT city

FROM authors

WHERE NOT EXISTS

(SELECT *

FROM publishers

WHERE authors.city = publishers.city)

или

SELECT DISTINCT city

FROM authors

WHERE NOT IN

(SELECT city

FROM publishers)

11