Формирование структур вложенных запросов

Формирование запросов на основе соединения таблиц

Очевидно, что с помощью соединения несложно сформировать запрос на обработку данных из нескольких таблиц. Кроме того, в такой запрос можно включить любые части предложения SELECT, рассмотренные ранее (выражения с использованием функций, группирование с отбором указанных групп и упорядочением полученного результата). Следовательно, соединения позволяют обрабатывать множество взаимосвязанных таблиц как единую таблицу, в которой собрана информация о нескольких сущностей. Различные виды реляционной операции соединения были рассмотрены в п.3.5. В этом пункте остановимся на следующих видах соединений:

  1. эквисоединение (по равенству полей)
  2. соединение через справочную целостность;
  3. соединение таблицы с собой (рекурсия);
  4. внешнее соединение.
Полное имя столбца таблицы фактически состоит из имени таблицы, сопровождаемого точкой и затем имени столбца, например: Продавцы.snum , Продавцы.city, Порядки.odateРанее мы могли опускать имена таблиц при указании столбцов, потому что запрашивали только одну таблицу одновременно, а SQL достаточно интеллектуален, чтобы присвоить соответствующий префикс имени таблицы. Даже, если запрос включает несколько таблиц, еще можно опускать имена таблиц, если все столбцы имеют различные имена. Но это не всегда так бывает. Например, если в одном запросе использованы два столбца city, то нужно указать их с именами Продавцы.city или Заказчики.city, чтобы SQL мог их различать.Пример 4.22 Предположим, что необходимо поставить в соответствии каждому продавцу его заказчиков в том городе, в котором они живут: SELECT Заказчики.cname, Продавцы.sname, Продавцы.city FROM Продавцы, Заказчики WHERE Продавцы.city = Заказчики.city;

Результат запроса:

cname cname city

Хофман Пил Лондон

Клеменс Пил Лондон

Луи Серенс Мехико

Киснерос Серенс Мехико

Хофман Мотика Лондон

Клеменс Мотика Лондон

Алгоритм выполнения запроса в примере 4.22:

  1. вычисляется декартово произведение, получаем 35 строк (5х7);
  2. производится выборка из полученной таблицы только тех строк, для которых выполняется условие Продавцы.city = Заказчики.city;
  3. из полученной на шаге 2 таблицы выбираются только 3 указанных столбца (проекция).

В этом запросе использовалось эквисоединение.

Пример 4.23 Показать для каждого продавца имена всех заказчиков, которых он обслуживают: SELECT Заказчики.cname, Продавцы.sname FROM Продавцы, Заказчики WHERE Продавцы.snum = Заказчики.snum;В этом примере использовано соединение таблиц через справочную целостность, поскольку поле snum в таблице Продавцы является первичным ключом, а в таблице Заказчики – внешним ключом.Можно создавать запросы, использующие соединение более чем двух таблиц.Пример 4.24 Предположим, что нужно найти все порядки заказчиков, не находящихся в тех городах, где живут их продавцы. Для этого необходимо связать все три таблицы: SELECT onum, cname, Порядки.cnum, Порядки.snum FROM Продавцы, Заказчики, Порядки WHERE Заказчики.city < > Продавцы.city AND Порядки.cnum = Заказчики.cnum AND Порядки.snum = Продавцы.snum;

Результат вывода:

onum cname cnum snum ------ ------- ----- ----- 3001 Киснерос 2008 1007 3002 Перера 2007 1004 3006 Джованни 2002 1003 3007 Грасс 2004 1002

3010 Грасс 2004 1002

В запросе таблица может соединяться сама с собой. В этом случае для экземпляров таблицы задаются псевдонимы, которые определяются в предложении FROM после имени таблицы. Пример 4.25 Найти все пары заказчиков с одинаковым рейтингом:SELECT a.cname, b.cname, a.rating FROM Заказчики a, Заказчики b WHERE a.rating = b.rating;Результат запроса:cname cname ratingХофман Хофман 100Хофман Клеменс 100Хофман Перера 100Джованни Джованни 200Джованни Луи 200Луи Джованни 200Луи Луи 200Грасс Грасс 300Грасс Киснерос 300Клеменс Хофман 100Клеменс Клеменс 100Клеменс Перера 100Киснерос Грасс 300Киснерос Киснерос 300Перера Хофман 100Перера Клеменс 100Перера Перера 100Обратите внимание на избыточность в выводе: каждая комбинация заказчиков выведена дважды; выводится комбинация строки сама с собой. Для устранения избыточности необходимо добавить еще одно условие в предикат, чтобы сделать предикат ассиметричным, и те же самые значения в обратном порядке не будут выбираться снова, например:Пример 4.26 SELECT a.cname, b.cname, a.rating FROM Заказчики a, Заказчики b WHERE a.rating = b.rating AND a.cname < b.cname;Вывод в этом случае будет содержать только 5 строк.В Access для соединения таблиц используется фраза JOIN. К их числу относится операция внутреннего соединения (INNER JOIN) и операции внешнего соединения (LEFT JOIN и RIGHT JOIN). Эти операции могут использоваться в любом предложении FROM. Операция INNER JOIN объединяет записи из двух таблиц, если связывающие поля содержат одинаковые значения. LEFT JOIN выбирает все записи из левой таблицы, даже. Если в правой таблице нет совпадающих значений. Это относится и к операции RIGHT JOIN, только все записи выбираются из правой таблицы

Синтаксис предложения FROM:

FROM таблица_1 [INNER | LEFT| RIGHT | JOIN таблица_2 ON таблица_1.поле_1 оператор таблица_2.поле_2],

где таблица_1, таблица_2 – имена таблиц, которые подлежат соединению;

поле_1, поле_2 – имена полей, используемые для связи;

оператор – чаще всего «=».

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

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

Подзапрос - это запрос, который может входить в предикаты условия выборки предложений WHERE и HAVING оператора SELECT или других операторов SQL, использующих WHERE предложение. Вложенный подзапрос может содержать в своей WHERE (HAVING) фразе другой вложенный подзапрос и т.д. Нетрудно догадаться, что вложенный подзапрос создан для того, чтобы при отборе строк таблицы, сформированной основным запросом, можно было использовать данные из других таблиц. В SQL/89 к подзапросам применяется то ограничение, что результирующая таблица должна содержать в точности один столбец. Поэтому в синтаксических правилах, определяющих подзапрос, вместо списка выборки указано арифметическое выражение. Заметим еще, что поскольку подзапрос всегда вложен в некоторый другой оператор SQL, то в качестве констант в арифметическом выражении выборки и логических выражениях разделов WHERE и HAVING можно использовать значения столбцов текущих строк таблиц, участвующих в запросах (подзапросах) более внешнего уровня.

Существуют простые и коррелированные (соотнесенные) вложенные подзапросы. Они включаются в WHERE (HAVING) фразу с помощью операторов IN, EXISTS, ALL, ANY или одного из условий сравнения ( = | <> | < | <= | > | > = ). Простые вложенные подзапросы обрабатываются системой «снизу вверх». Первым обрабатывается вложенный подзапрос самого нижнего уровня. Множество значений, полученное в результате его выполнения, используется при реализации подзапроса более высокого уровня и т.д.