Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
М. ГРУБЕР_SQL.doc
Скачиваний:
22
Добавлен:
18.04.2019
Размер:
1.4 Mб
Скачать

Работа с sql

  1. Напишите запрос, который бы вывел все пары продавцов, живущих в одном и том же городе. Исключите комбинации продавцов с ними же, а также дубликаты строк, выводимых в обратном порядке.

  2. Напишите запрос, который вывел бы все пары Заказов по данным заказчикам, именам этих заказчиков, и исключал дубликаты из вывода, как в предыдущем вопросе.

  3. Напишите запрос, который вывел бы имена (cname) и города (city) всех заказчиков с такой же оценкой (rating) как у Hoffman. Напишите запрос, использующий поле cnum Hoffman, а не его оценку, так, чтобы оно могло быть использовано, если его оценка вдруг изменится.

(См. Приложение A для ответов.)

10

Вставка одного запроса внутрь другого

В КОНЕЦ ГЛАВЫ 9, МЫ ГОВОРИЛИ, ЧТО ЗАПРОСЫ могут управлять другими запросами. В этой главе вы узнаете, как это делается (большей частью), помещая запрос внутрь предиката другого запроса, и используя вывод внутреннего запроса в верном или неверном условии предиката. Вы сможете выяснить, какие виды операторов могут использовать подзапросы и посмотреть как подзапросы работают со средствами SQL, такими как DISTINCT, с составными функциями и выводимыми выражения. Вы узнаете, как использовать подзапросы с предложением HAVING и получите некоторые наставления, как правильно использовать подзапросы.

Как работает подзапрос?

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

Предположим что мы знаем имя sname продавца Motika, но не знаем его номер snum, и хотим извлечь все его Заказы из таблицы Заказов. Имеется один способ, чтобы сделать это (вывод показывается в Рисунке 10.1):

SELECT * FROM Orders WHERE snum = (SELECT snum FROM Salespeople WHERE sname = 'Motika');

Чтобы оценить внешний (основной) запрос, SQL сначала должен оценить внутренний запрос (или подзапрос) внутри предложения WHERE. Он делает это так, как и должен делать запрос имеющий единственную цель — отыскать через таблицу Продавцов все строки, где поле sname равно значению Motika, и затем извлечь значения поля snum этих строк.

Единственной найденной строкой, естественно, будет snum = 1004. Однако SQL не просто выдает это значение, а помещает его в предикат основного запроса вместо самого подзапроса, так чтобы предиката прочитал, что snum = 1004

=============== SQL Execution Log ============== | SELECT * | | FROM Orders | | WHERE snum = | | (SELECT snum | | FROM Salespeople | | WHERE sname = 'Motika'); | |=================================================| | onum amt odate cnum snum | | ----- ------- ---------- ----- ----- | | 3002 1900.10 10/03/1990 2007 1004 | ================================================= Рисунок 10.1. Использование подзапроса.

Основной запрос затем выполняется как обычно с вышеупомянутыми результатами. Конечно же, подзапрос должен выбрать один и только один столбец, а тип данных этого столбца должен совпадать с тем значением, с которым он будет сравниваться в предикате. Часто, как показано выше, выбранное поле и его значение будут иметь одинаковые имена (в этом случае, snum), но это необязательно.

Конечно, если бы мы уже знали номер продавца Motika, мы могли бы просто напечатать

WHERE snum = 1004

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