Содержание
Подзапросы в Transact SQL — запрос внутри другого запроса.
Представим ситуацию: есть обычный простой запрос, который работает с одной таблицей. Внутри него можно написать еще один запрос к другой таблице, и в итоге появится новый столбец в нашей исходной таблице.
Подзапросы можно писать в любом месте запроса (SELECT, FROM, WHERE).
Пример:
SELECT title,price, ( SELECT Count(*) FROM orders) FROM titles
Пример выше — это запрос без корреляции, т.е. 2 запроса между собой никак не связаны.
На практике чаще применяют корреляционные запросы, когда запросы зависят друг от друга.
Рассмотрим пример. Есть 2 таблицы: с книгами и с продажами этих книг. Получим отчет — название проданной книги и количество экземпляров:
SELECT title,price, ( SELECT Sum(qty) FROM sales WHERE title_id=titles.title_id) FROM titles
Другой пример. Есть таблица с товарами разных категорий. Информация о категориях лежит в другой таблице (categories). Узнаем, сколько товаров в каждой категории:
SELECT categoryName, ( SELECT Count(*) FROM products WHERE categoryID=categories.categoryID) FROM categories
Подзапросы в FROM
Рассмотрим на примере. SELECT возвращает список городов, в котором живет хотя бы один продавец.
SELECT DISTINCT city FROM customers
Этот запрос можно использовать как таблицу для построения новых запросов. Представим, что полученный список городов уже есть в отдельной таблице таблице. Теперь данный запрос заключим в скобки, чтобы использовать внутри другого запроса:
SELECT * FROM (SELECT DISTINCT city FROM customers)MyTable
В примере надо придумать синоним для виртуальной таблицы (MyTable) — это обязательно для всех корреляционых запросов во избежание синтаксической ошибки. И с полученной таблицей можно дальше работать, как обычно.
Подзапрос в WHERE
SELECT * FROM employees WHERE employeeID IN ( SELECT employeeID FROM orders WHERE Year(order_date)=2012)
По аналогией с конструкцией FROM. Внутри WHERE пишем то, чего не хватает в нашей таблице. Эти сведения берем из другой table.
Еще пример:
SELECT CustomerID, ContactName,( SELECT Sum(UnitPrice*Quantity*(1-Discount)) FROM [Order Details] WHERE OrderID IN ( SELECT OrderID FROM Orders WHERE CustomerID=CUstomers.CustomerID) ) AS TotalSum FROM Customer
Хотя использование подзапросов и позволяет решить сложные задачи при работе с БД, но сами подзапросы генерируют очень большой код для общего запроса к базе данных. И бывает, что запрос занимает всю страницу, возникают сложности с его чтением и разбором.