Многие запросы можно выполнять как объединение и как подзапрос.
Пример SELECT Cont.FirstName, Cont.LastName FROM Person.Contact Cont WHERE Cont.ContactID IN (SELECT Emp.ContactID FROM HumanResources.Employee Emp WHERE Emp.HireDate LIKE '%1997%' ) | Пример SELECT Cont.FirstName, Cont.LastName FROM HumanResources.Employee Emp JOIN Person.Contact Cont ON Emp.ContactID=Cont.ContactID WHERE Emp.HireDate LIKE '%1997%'; |
Посмотрите план выполнения запросов с помощью меню Запрос – Показать план выполнения | |
Объединения представляют собой основу многотабличных запросов в SQL. Объединения являются средством, выявляющим отношения, существующие между данными. Т.е. объединения применяются тогда, когда необходимо получить данные из нескольких таблиц одновременно. Подзапросы обычно ближе к словесному описанию запроса, облегчают написание и чтение запроса. Подзапросы используются, в основном, когда необходимо вывести данные из таблиц, к которым обращается внешний запрос, а данные из таблиц подзапроса используются для сравнения или поиска записи во внешней таблице. Если есть вероятность, что подзапрос вернет NULL, то рекомендуется не использовать подзапрос. | |
Пример SELECT Cont.FirstName, Cont.LastName, Emp.BirthDate FROM HumanResources.Employee Emp JOIN Person.Contact Cont ON Emp.ContactID=Cont.ContactID WHERE Emp.HireDate LIKE '%1997%'; | Пример SELECT Cont.FirstName, Cont.LastName FROM Person.Contact Cont WHERE Cont.ContactID IN (SELECT ContactID FROM HumanResources.Employee WHERE VacationHours<= (SELECT AVG (VacationHours) FROM HumanResources.Employee )); |
Не может быть выполнен с помощью подзапроса, так как выводит данные из нескольких таблиц | Не может быть выполнен с помощью объединения, так как требуется вычисление агрегирующей функции и возврат значения во внешний запрос |
Выбор применяемых операций определяется удобством чтения запроса, производительностью конкретной СУБД, а также семантикой запроса. | |
Пример SELECT VendorID FROM Purchasing.ProductVendor WHERE ProductID NOT IN (SELECT ProductID FROM Production.Product WHERE Style='M') | Пример SELECT VendorID FROM Purchasing.ProductVendor JOIN Production.Product ON Purchasing.ProductVendor.ProductID=Production.Product.ProductID WHERE Style<>'M' |
Результатом выполнения запроса будет список поставщиков, которые не поставляют товары для женщин. | Результатом выполнения запроса будет список поставщиков, которые поставляют какой-либо товар, не являющийся товаром для женщин. |
Подзапрос, содержащий NOT IN, нельзя преобразовать в эквивалентное объединение. | |
Хотя конечный результат получается тем же самым, многие СУБД обрабатывают объединения намного быстрее, чем подзапросы. Стоит поэкспериментировать с тем и другим, чтобы определить, какой запрос работает быстрее. | |
Пример SELECT Employee.EmployeeID FROM HumanResources.Employee Boss JOIN HumanResources.Employee Employee ON Boss.EmployeeID=Employee.ManagerID WHERE Boss.SickLeaveHours>=Employee.VacationHours; | Пример SELECT Emp.EmployeeID FROM HumanResources.Employee Emp WHERE Emp.VacationHours<= (SELECT Boss.SickLeaveHours FROM HumanResources.Employee Boss WHERE Boss.EmployeeID=Emp.ManagerID ) |
Посмотрев меню Запрос – Показать план выполнения, можно увидеть, что внутренний оптимизатор запросов выполняет оба примера одинаково. | |
Иногда вместо множественных условий WHERE удобнее использовать оператор UNION. | |
Пример SELECT ProductID, Name, MakeFlag FROM Production.Product WHERE Style='U' OR ProductID=400 | Пример SELECT ProductID, Name, MakeFlag FROM Production.Product WHERE Style='U' UNION SELECT ProductID, Name, MakeFlag FROM Production.Product WHERE ProductID=400 |
Если условие фильтрации окажется более сложным или если понадобится выбирать данные из многих таблиц (а не только из одной), то оператор UNION может значительно упростить процесс | |
В большинстве СУБД используется внутренний оптимизатор запросов, комбинирующий операторы SELECT, прежде чем СУБД начинает их обработку. Теоретически это означает, что, с точки зрения производительности, нет реальной разницы между различными вариантами исполнения одного и того же запроса (объединение-подзапрос, where-union). На практике многие оптимизаторы запросов не всегда выполняют свою работу так хорошо, как следовало бы. Лучшим вариантом было бы протестировать оба метода и посмотреть, какой из них вам лучше подходит. |