Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка SQL(14) (оптимизация).docx
Скачиваний:
62
Добавлен:
17.03.2015
Размер:
452.16 Кб
Скачать

4.2.2. Использование одной и той же таблицы во внешнем и вложенном подзапросе

Пример 28.

Выдать номера Блюд, в состав которых входят продукты, необходимые для приготовления сырников.

SELECT DISTINCT Блюдо

FROM Соcтав

WHERE Продукт IN ( SELECT Продукт

FROM Состав

WHERE Блюдо = 18);

Отметим, что ссылка на Состав во вложенном подзапросе означает не то же самое, что ссылка на Состав во внешнем запросе. В действительности, два имени Состав обозначают различные значения. Чтобы этот факт стал явным, полезно использовать псевдонимы, например, С1 и С2:

SELECT DISTINCT Блюдо

FROM Соcтав С1

WHERE С1. Продукт IN ( SELECT Продукт

FROM Состав С2

WHERE С2.Блюдо = 18);

Здесь С1 и С2 – произвольные псевдонимы таблицы Состав, определяемые во фразе FROM и используемые как явные уточнители во фразах SELECT и WHERE. Напомним, что псевдонимы определены лишь в пределах одного запроса.

4.2.3. Использование агрегатных функций в подзапросах.

Любой запрос, использующий одиночную функцию агрегата без предложения GROUP BY, будет выбирать одиночное значение, а значит, может быть использован для сравнения в основном предикате.

Пример 29.

Необходимо найти самые дешевые продукты:

SELECT p.Продукт, Цена

FROM Продукты p JOIN Наличие n ON p.ID_продукта = n.Продукт

WHERE Цена = ( SELECT MIN (Цена) FROM Наличие);

Результат

Продукт

Цена

Зелень

34,96

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

Следует заметить, что если агрегатные функции используются с предложением GROUP BY, то подзапрос может вернуть многочисленные значения. Они, следовательно, не допустимы в подзапросах такого характера. Даже если GROUP BY и HAVING используются таким способом, что только одна группа выводится с помощью подзапроса, команда будет отклонена в принципе.

Если не удается построить подзапрос, возвращающий единственное значение вы должны использовать предикаты IN, ANY или ALL. Но следует заметить, что предикаты BETWEEN, LIKE, и IS NULL не могут использоваться с подзапросами

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

4.2.4. Подзапросы в предложении having.

Подзапросы могут использоваться внутри предложения HAVING.

Пример 30.

Найти самые дешевые блюда.

SELECT b.Блюдо,

cast(SUM (s.Вес*n.Цена/1000)+b.Труд as numeric(6,2)) as Стоимость

FROM (Блюда b JOIN Состав s ON b.ID_блюда =s.Блюдо )

JOIN Наличие n ON s.Продукт = n.Продукт

GROUP BY b.Блюдо, b.Труд

HAVING (SUM (s.Вес*n.Цена/1000)+b.Труд) = ( SELECT MIN(стоимость)

FROM (SELECT b.Блюдо, SUM (s.Вес*n.Цена/1000)+b.Труд as Стоимость

FROM (Блюда b JOIN Состав s ON b.ID_блюда = s.Блюдо )

JOIN Наличие n ON s.Продукт = n.Продукт

GROUP BY b.Блюдо, b.Труд ) a

);

Результат

Блюдо

Цена

Кофе черный

2,33

Этот запрос ищет для каждого блюда стоимость (псевдоним a), затем из этих данных выбирает минимум (подается на вход HAVING). Этот минимум используется для отбора блюд для вывода результата основного запроса.