Связанные подзапросы. Оператор EXISTS




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

Пример: Построить список студентов, сдававших экзамен 11/01/01

Sname
C-2
C-3

SELECT sname FROM студент

WHERE 11/01/01 IN

(SELECT odate FROM оценка WHERE snum = osnum);

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

  • Из таблицы внешнего запроса выбирается очередная строка-кандидат
  • Выполняется подзапрос с использованием значения строки-кандидата.
  • Оцениваются условия внешнего запроса, по результатам чего строка-кандидат включается в результат или нет.
  • Если не конец таблицы внешнего запроса, то переход к пункту 1.

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

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

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

opnum osnum odate Ocen
    13/01/01  

SELECT * FROM оценка01

WHERE ocen >

(SELECT AVG(ocen) FROM оценка02

WHERE 02.osnum=01.osnum);

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

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

SELECT opnum, AVG(ocen) FROM оценка01

opnum AVG
  3,67

GROP BY opnum

HAVING AVG(ocen)<

(SELECT MAX(ocen)-1 FROM оценка 02

WHERE 01.opnum=02.opnum);

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

 

При использовании вложенных подзапросов в условных выражениях внешнего подзапроса могут использоваться служебные операторы EXIST, ANY, ALL, COME.

EXIST – это оператор, генерирующий значения истина\ложь. Это значит, что его можно использовать самостоятельно в условиях или комбинировать с логическими выражениям с помощью AND, OR, NOT. Используя подзапрос в качестве аргумента, этот оператор возвращает истину, если результат подзапроса не пуст.

Пример: получить фамилии преподавателей, принимавших экзамен с 10/01/01 по 11/01/01.

 

Pname
П-1

SELECT pname FROM преподаватель

WHERE EXIST

(SELECT*FROM оценка

WHERE odate >=10/01/01 AND pnnum=opnum);

 

В этом запросе не имеет значения какие поля заданы в предложении SELECT внутреннего подзапроса. Важно в принципе наличие строк таблицы ОЦЕНКА, удовлетворяющих условию. Эту задачу можно решить и с помощью соединения таблиц:

SELECT DISTINCT FROM преподаватель, оценка

WHERE odate >=10/01/01 AND =<11/01/01 AND pnum=opnum;

Данный запрос выглядит короче, но с EXIST – эффективнее работает, по следующим причинам:

  • Для каждой записи таблицы ПРЕПОДАВАТЕЛЬ, таблица ОЦЕНКА просматривается только до первого выполнения условия.
  • Из выходных данных внешнего запроса не требуется удалять совпадающие значения.

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

SELECT DISTINCT spdp FROM студент С1

Spdp
 

WHERE EXIST

(SELECT FROM студент С2

WHERE C1.snum <> C2.snum

AND C1.spdp=C2.spdp);

EXIST также можно комбинировать соединениями.

 

Пример: получить фамилии преподавателей, имеющих более 1 дипломника.

SELECT DISTINCT pname

Pname
П-1

FROM преподаватель INNER JOIN

Студент С1 ON pnum-spdp

WHERE EXIST

(SELECT*FROM студент C2

WHERE C1.snum <> C2.snum

AND C1.spdp=C2.spdp);

Рассмотрим еще один пример вложенных подзапросов: получить фамилии преподавателей, имеющих студентов, которые сдавали экзамен более 1 раза.

SELECT pname FROM преподаватель

Pname
П-3

WHERE EXIST

(SELECT*FROM студент

WHERE 1<(SELECT count(*)

FROM оценка WHERE snum=osnum

AND pnum=opnum));

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: