В предыдущем разделе мы рассмотрели самые простые способы сочетания таблиц – с помощью предложений WHERE и INNER JOIN. Эти сочетания называются внутренними сочетаниями или сочетаниями по эквивалентности. Однако SQL имеет в своем арсенале гораздо больше возможностей совместить таблицы, а именно существуют и другие виды объединений: внешние сочетания, естественные сочетания и самосочетания. Но для начала рассмотрим, каким образом мы можем присваивать таблицам псевдонимы, поскольку в дальнейшем мы будем вынуждены использовать полные названия полей (Таблица.Поле), которыми без сокращений будет очень трудно оперировать из-за их большой длины.
В предыдущем разделе мы узнали, как можно использовать псевдонимы для ссылки на поля таблицы или на расчетные поля. SQL также предоставляет нам возможность использовать псевдонимы вместо имен таблиц. Это дает нам такие преимущества, как более короткий синтаксис SQL и позволяет многократно использовать одну и ту же таблицу в операторе SELECT.
Run SQLSELECT Seller_name, SUM(Amount) AS Sum1
FROM Sellers AS S, Sumproduct AS SP
WHERE S.City = SP.City
GROUP BY Seller_name
Мы отразили общую сумму реализуемого товара по каждому продавцу. В нашем SQL запросе мы использовали следующие псевдонимы: для расчетного поля SUM(Amount) псевдоним Sum1, для таблицы Sellers псевдоним S и для Sumproduct псевдоним SP. Заметим, что псевдонимы таблиц могут быть применены также и в других предложениях как ORDER BY, GROUP BY и других.
Рассмотрим пример. Предположим, нам нужно узнать адрес продавцов, торгующих в той же стране, что и John Smith. Для этого создадим следующий запрос:
Run SQLSELECT Address, City, Country, Seller_name
FROM Sellers
WHERE Country = (SELECT Country
FROM Sellers
WHERE Seller_name = 'John Smith')
Также эту задачу мы можем решить и через самосочетание, прописав следующий код:
Run SQLSELECT S1.Address, S1.City, S1.Country, S1.Seller_name
FROM Sellers AS S1, Sellers AS S2
WHERE S1.Country = S2.Country AND S2.Seller_name = 'John Smith'
Для решения этой задачи использовались псевдонимы. Первый раз для таблицы Sellers присвоили псевдоним S1, второй раз – псевдоним S2. После этого эти псевдонимы можно использовать в качестве имен таблиц. В операторе WHERE мы к названию каждого поля добавляем префикс S1, для того чтобы СУБД понимающая поля какой таблицы нужно выводить (поскольку мы из одной таблицы сделали две виртуальные). Предложение WHERE сначала объединяет таблицы, а затем фильтрует данные второй таблицы по полю Seller_name, чтобы вернуть только необходимые значения.
Самосочетание часто используют для замены подзапросов, выбирающих данные из той же таблицы, что и внешний оператор SELECT. Хотя конечный результат получается тем самым, многие СУБД прорабатывают сочетание гораздо быстрее, чем подзапросы. Следует поэкспериментировать, чтобы определить, какой запрос работает быстрее.
Естественное сочетание – это сочетание, в котором вы выбираете только не повторяющиеся столбцы. Обычно это делается с помощью записи (SELECT*) для одной таблицы и указанием перечня полей – для остальных таблиц. К примеру:
Run SQLSELECT SP.*, S.Country
FROM Sumproduct AS SP, Sellers AS S
WHERE SP.City = S.City
В этом примере метасимвол (*) используется только для первой таблицы. Все остальные столбцы указаны явно, поэтому дубликаты столбцов не выбираются.
Обычно при объединении связывают строки одной таблицы с соответствующими строками другой, однако в некоторых случаях может потребоваться включать в результат строки, не имеющие связанных строк в другой таблице (т.е. выбираются все строки из одной таблицы и добавляются только связаны строки из другой). Сочетание такого типа называется внешним. Для этого используются ключевые слова OUTER JOIN...ON... с приставкой LEFT или RIGHT.
Рассмотрим пример, предварительно добавив в таблицу Sellers нового продавца – Semuel Piter, который еще нет продаж:
Run SQLSELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers2
LEFT OUTER JOIN Sumproduct
ON Sellers2.City = Sumproduct.City
GROUP BY Seller_name
Данным запросом мы извлекли список всех продавцов в базе и подсчитали для них общее количество проданного товара за все месяцы. Видим, что по новому продавцу Semuel Piter отсутствуют продажи. Если бы мы использовали внутреннее сочетание, то нового продавца мы бы не увидели, поскольку у него нет записей в таблице Sumproduct. Мы также можем изменять направление сочетания не только прописывая LEFT или RIGHT, но и просто изменяя порядок таблиц (то есть такие две записи будут давать одинаковый результат: Sellers LEFT OUTER JOIN Sumproduct и Sum JOIN Sellers).
Также некоторые СУБД позволяют осуществлять внешнее сочетание по упрощенной записи, используя знаки *= и =*, что соответствует LEFT OUTER JOIN и RIGHT OUTER JOIN соответственно. Таким образом, предварительный запрос можно было бы переписать так:
SELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers, Sumproduct
WHERE Sellers.City *= Sumproduct.City
К сожалению, MS Access не поддерживает сокращенную запись для внешнего сочетания.
Также существует и другой тип внешнего сочетания – полное внешнее сочетание, отображающее все строки из обеих таблиц и связывающее только те, которые могут быть связаны. Синтаксис полного внешнего сочетания:
SELECT Seller_name, Product
FROM Sellers
FULL OUTER JOIN Sumproduct
ON Sellers.City = Sumproduct.City
Опять же, полное внешнее соединение не поддерживают следующие СУБД: MS Access, MySQL, SQL Server и Sybase. Как обойти эту несправедливость, мы рассмотрим в следующей главе.