Использование вложенных SQL-запросов
Коррелированные подзапросы
В операторе SELECT из внутреннего подзапроса можно ссылаться на столбцы внешнего запроса, указанного во фразе SELECT. Такой подзапрос выполняется для каждой строки таблицы, определяя условие ее вхождения в формируемый результирующий набор.
Например:
SELECT * from tbl1 t1 WHERE f2 IN (SELECT f2 FROM tbl2 t2 WHERE t1.f3=t2.f3);
В данном случае для каждой строки таблицы tbl1 будет проверяться условие, что значение поля f2 совпадает со значением строки таблицы tbl2, где значение поля f3 равно значению поля f3 внешней таблицы ( tbl1 ). Это простейший пример коррелированного подзапроса.
Очень часто требуется, чтобы подзапрос использовал те же данные, что и внешняя таблица. В этом случае обязательно применение алиасов.
Например:
SELECT * from tbl1 t_out WHERE f2< (SELECT AVG(f2) FROM tbl1 t_in WHERE t_out.f1= t_in.f1);
В случае коррелированного подзапроса во фразе HAVING можно использовать только агрегирующие функции, так как каждый раз на момент выполнения подзапроса в качестве проверяемой строки, к значениям которой имеет доступ подзапрос, выступает результат группирования строк на основе агрегирующих функций основного запроса.
Например:
SELECT f1, COUNT(*), SUM(f2) from tbl1 t1 GROUP BY f1 HAVING SUM(f2)> (SELECT MIN(f2)*4 FROM tbl1 t1_in WHERE t1.f1=t1_in.f1);
Построение предиката для подзапроса, возвращающего несколько строк
Если в предикате надо сравнить значение с некоторым множеством, то, как было показано выше, можно использовать оператор IN.
Для того чтобы проверить, существуют ли строки, удовлетворяющие конкретному условию подзапроса, применяется оператор EXISTS.
Например:
SELECT f1,f2,f3 from tbl1 WHERE EXISTS (SELECT * FROM tbl1 WHERE f4='10/11/2003');
Этот запрос будет формировать не пустой результирующий набор только в том случае, если в какое-либо значение столбца f4 таблицы была занесена дата, например: '10/11/2003'.
Преимущество применения оператора EXISTS с результатами подзапроса состоит в том, что подзапрос может возвращать как множество строк, так и множество столбцов.
При коррелированном подзапросе оператор EXISTS будет вычисляться каждый раз для каждой строки внешнего запроса.
В стандарте SQL-92 не предусмотрено использование в подзапросах, к которым применяется оператор EXISTS агрегирующих функций. Однако некоторые СУБД позволяют такой вид подзапросов.
Для использования результата подзапроса в предикате также применяются операторы ANY и ALL, которые были подробно рассмотрены в предыдущих лекциях.
Приведем пример использования оператора ANY:
SELECT f1,f2,f3 from tbl1 WHERE f3 = ANY (SELECT f3 FROM tbl2);
Данный оператор определяет, что в результирующий набор будут включены все строки, значение столбца f3 которых присутствует в таблице tbl2.