Теоретико-множественные операции
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

 

Над наборами записей, содержащихся в таблицах базы данных и/или возвращаемых запросами, можно совершать теоретико-множественные операции, такие как декартово произведение, объединение, пересечение и вычитание.

 

Декартово произведение наборов записей

 

Запрос вида             SELECT списокСтолбцов

FROM T1, T2, ..., Tn;

возвращает набор записей, полученный в результате декартового произведения наборов записей из таблиц T1, T2, ..., Tn. Таблицы, указанные в операторе FROM, могут быть как таблицами базы данных, так и виртуальными таблицами, возвращаемыми какими-нибудь запросами.

Иногда требуется получить декартово произведение таблицы самой на себя. В этом случае необходимо применить различные псевдонимы для этой таблицы, например:

SELECT списокСтолбцов

FROM MyTab T1, MyTab T2;

Попытка выполнить запрос:

SELECT списокСтолбцов

FROM MyTab, MyTab;

приведет к ошибке.

В списке столбцов следует использовать полные имена с помощью точечной записи.

Для декартова произведения в SQL также допустим синтаксис с ключевыми словами CROSS JOIN:

SELECT списокСтолбцов

FROM MyTab T1 CROSS JOIN MyTab T2;

Запросы на декартово произведение сами по себе очень редко используются. Они приобретают некоторый смысл, если применяются с секцией WHERE.

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

 

Рейсы

Начальный_пункт Конечный_пункт
A B
A C
A F
B C
B G
B F
C E
C D
D H

 

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

SELECT T1.Начальный_пункт, T2.Конечный_пункт

FROM Рейсы T1, Рейсы T2

WHERE T1.Конечный_пункт = T2.Начальный_пункт;

Сначала запрос выполняет декартово произведение таблицы Рейсы на эту же таблицу. В результате получается таблица с четырьмя столбцами: T1.Начальный_пункт, T1.Конечный_пункт, T2.Начальный_
пункт, T2.Конечный_пункт. Затем из полученной таблицы выбираются такие записи, в которых T1.Конечный_пункт = T2.Начальный_пункт. Это и есть пары пунктов, между которыми находится один промежуточный пункт. Наконец, из четырех столбцов выделяются только два: T1.Начальный_пункт и T2.Конечный_пункт. Результат запроса приведен ниже.

 

Рейсы

Начальный_пункт Конечный_пункт
A C
A G
A F
A E
A D
B E
B D
C H

 


Объединение наборов записей

 

Нередко требуется объединить наборы записей двух или более таблиц с похожими структурами в одну таблицу. Иначе говоря, к набору записей, возвращаемых одним запросом, требуется добавить записи, возвращаемые другим запросом. Для этого служит оператор UNION:

                Запрос1

                UNION

                Запрос2;

При этом в результатной таблице остаются только отличающиеся записи. Чтобы сохранить в ней все записи, следует после оператора UNION написать ключевое слово ALL.

Например, таблицы Коробки и Крышки имеют однотипные столбцы Размер, Количество и Цвет. Тогда, чтобы получить общий список данных и о коробках, и о крышках, достаточно выполнить следующий запрос:

SELECT Размер, Количество, Цвет

FROM Коробки

UNION

SELECT Размер, Количество, Цвет

FROM Крышки;

Оператор UNION можно применять только к таблицам, удовлетворяющим следующим условиям совместимости:

· количества столбцов объединяемых таблиц должны быть равны;

· данные в соответствующих столбцах объединяемых таблиц должны иметь совместимые типы данных. Например, символьные (строковые) типы CHAR и VARCHAR совместимы, а числовой и строковый типы не совместимы.

Имена соответствующих столбцов и их размеры могут быть различными. Важно, чтобы количества столбцов были равны, а их типы были совместимы.

Пусть требуется получить сведения о том, в какие пункты можно попасть, сделав не более одной пересадки (т.е. без пересадок или с одной пересадкой). Для этого достаточно объединить записи исходной таблицы Рейсы с результатом запроса о достижимости через один промежуточный пункт:

SELECT Начальный_пункт, Конечный_пункт

FROM Рейсы

UNION

SELECT T1.Начальный_пункт, T2.Конечный_пункт

FROM Рейсы T1, Рейсы T2

WHERE T1.Конечный_пункт = T2.Начальный_пункт;

Пересечение наборов записей

 

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

                Запрос1

                INTERSECT

                Запрос2;

При этом в результатной таблице остаются только отличающиеся записи. Чтобы сохранить в ней повторяющиеся записи, следует после оператора INTERSECT написать ключевое слово ALL.

Если требуется получить список коробок, для которых есть совпадающие по размеру, количеству и цвету крышки, то можно воспользоваться следующим запросом:

SELECT Размер, Количество, Цвет

FROM Коробки

INTERSECT

SELECT Размер, Количество, Цвет

FROM Крышки;

 

Вычитание наборов записей

 

Для получения записей, содержащихся в одном наборе и отсутствующих в другом, служит оператор EXCEPT:

                Запрос1

                EXCEPT

                Запрос2;

Чтобы узнать, для всех ли коробок есть соответствующие им по размеру, количеству и цвету крышки, можно воспользоваться следующим запросом:

SELECT Размер, Количество, Цвет

FROM Коробки

EXCEPT

SELECT Размер, Количество, Цвет

FROM Крышки;

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

 

Внешние соединения

 

Все соединения таблиц, рассмотренные ранее, являются внутренними. Во всех примерах вместо ключевого слова JOIN можно писать INNER JOIN. Из таблицы, получаемой при внутреннем соединении, удаляются все записи, у которых нет соответствующих строк одновременно в обеих исходных таблицах. При внешнем соединении (OUTER JOIN) несоответствующие строки сохраняются. В этом и заключается отличие внешнего соединения от внутреннего.

В запросе, имеющем соединение, будем называть таблицу левой, если ее имя в операторе запроса предшествует ключевому слову JOIN, и правой, если ее имя следует за словом JOIN.

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

Существуют три разновидности внешних соединений.

 

Левое внешнее соединение

 

Операция LEFT JOIN (LEFT OUTER JOIN) возвращает все строки из левой таблицы, соединенные с теми строками из правой таблицы, для которых выполняется условие соединения. Если во второй таблице нет таких строк, то в качестве значений столбцов правой таблицы будут установлены значения NULL.

В базе данных booktown в таблице books содержится общая информация о книгах, а в таблице editions хранятся данные, относящиеся к конкретному изданию – код ISBN, издатель и дата публикации. В таблицу editions входит поле book_id, связывающее ее с полем id, которое является первичным ключом таблицы books.

Допустим, требуется информация о каждой книге вместе со всеми имеющимися кодами ISBN:

SELECT title, isbn

FROM books INNER JOIN editions

ON (books.id = editions.book_id);

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

Чтобы получить данные о каждой книге, следует воспользоваться следующим запросом:

SELECT title, isbn

FROM books LEFT OUTER JOIN editions

ON (books.id = editions.book_id);

Теперь в итоговом наборе будут присутствовать и те книги, у которых отсутствуют коды ISBN. В этом запросе использовано левое внешнее соединение. Выбор объясняется тем, что запрос должен вернуть названия книг, для которых существуют или не существуют коды ISBN. Поскольку таблица books стоит слева от ключевого слова JOIN, задача решается при помощи левого внешнего соединения.

 

Правое внешнее соединение

 

Операция RIGHT JOIN (RIGHT OUTER JOIN) возвращает все строки из правой таблицы, соединенные с теми строками из левой таблицы, для которых выполняется условие соединения. Если во второй таблице нет таких строк, то в качестве значений столбцов правой таблицы будут установлены значения NULL.

В качестве примера получим названия книг, у которых нет кодов ISBN:

SELECT title

FROM editions RIGHT JOIN books

ON (editions.book_id = books.id)

WHERE isbn IS NULL;

 

Полное внешнее соединение

 

Операция FULL OUTER JOIN выполняет одновременно и левое, и правое внешние соединения. В итоговом наборе наряду с соответствующими записями сохраняются и несоответствующие строки как из левой, так и из правой таблиц. Поля, которым не нашлось соответствия в другом наборе, заполняются значением NULL.

Если бы помимо названий всех книг (в том числе и не имеющих кодов ISBN) нас интересовали коды ISBN (в том числе и не соответствующие зарегистрированным в базе данных книгам), следовало бы воспользоваться полным внешним соединением:

SELECT title, isbn

FROM books FULL OUTER JOIN editions

ON (books.id = editions.book_id);

Ключевое слово OUTER во внешних соединениях PostgreSQL является необязательным. Определения LEFT JOIN, RIGHT JOIN и FULL JOIN подразумевают внешнее соединение.

Подзапросы

 

Подзапросом называется команда SELECT, заключенная в круглые скобки, которая выполняется в контексте другой команды SQL. Обычно подзапросы содержатся в условии оператора WHERE или HAVING внешнего запроса. В свою очередь, подзапрос может содержать другой подзапрос и т.д.

 

Простые подзапросы

 

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

Рассматривая простые подзапросы, следует выделить три частных случая:

· подзапросы, возвращающие единственное значение;

· подзапросы, возвращающие список значений из одного столбца таблицы;

· подзапросы, возвращающие набор записей.

 

Дата: 2019-02-19, просмотров: 217.