Sql Scholl
Распечатать страницу
Перейти на главную Карта сайта Отправить сообщение

Расширенные объединения

Внешние объединения

       Большинство объединений связывают строки одной таблицы со строками другой, но в некоторых случаях вам может понадобиться включать в результат строки, не имеющие связанных. Например, вы можете использовать объединения для решения следующих задач:

      •      подсчета количества заказов каждого клиента, включая клиентов, которые еще не сделали заказ;
      •      составления перечня продуктов с указанием количества заказов на них, включая продукты, которые никто из клиентов не захотел заказывать;
      •      вычисления средних объемов продаж с учетом клиентов, которые еще не сделали заказ.

       В каждом из этих случаев объединение должно включать строки, не имеющие ассоциирующихся с ними строк в связанной таблице. Объединение такого типа называется внешним.

Разница в синтаксисе

Важно отметить, что синтаксис, используемый при создании внешнего объединения, может несколько отличаться для различных реализаций SQL. Различные формы синтаксиса, описанные в следующем разделе, помогут вам работать с большинством реализаций, но все же обратитесь к документации своей СУБД и уточните, какой синтаксис следует использовать, прежде чем начинать работу.

       Следующий оператор SELECT позволяет выполнить простое внутреннее объединение. С его помощью выбирается список всех клиентов и их заказы:

SELECT Customers.cust_id, Orders.order_num
FROM Customers INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id;

       Синтаксис внешнего объединения похож на этот. Для выборки имен всех клиентов, включая тех, которые еще не сделали заказов, можно сделать следующее.

SELECT Customers.cust_id, Orders.order_num FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;



cust_id       order_num
------------  --------------------
1000000001     20005
1000000002     NULL
1000000003     20006
1000000004     20007
1000000005     20008

       Аналогично внутреннему объединению, которое мы рассматривали на прошлом уроке, в этом операторе SELECT используются ключевые слова OUTER JOIN для указания типа объединения (вместо указания его в предложении WHERE). Но, в отличие от внутренних объединений, которые связывают строки двух таблиц, внешние объединения включают в результат также строки, не имеющие связанных с ними строк. При использовании синтаксиса OUTER JOIN вы должны использовать ключевое слово RIGHT или LEFT, чтобы указать таблицу, все строки которой будут включены в результат (RIGHT для таблицы, имя которой стоит справа от OUTER JOIN, LEFT — для той, имя которой значится слева).

        В предыдущем примере используются ключевые слова LEFT OUTER JOIN для выборки всех строк таблицы, указанной в левой части предложения FROM (таблицы Customers). Чтобы выбрать все строки из таблицы, указанной справа, используйте правое внешнее объединение (RIGHT OUTER JOIN), как показано в следующем примере.

SELECT Customers.cust_id, Orders.order_num FROM Customers RIGHT OUTER JOIN Orders ON Orders.cust_id = Customers.cust_id;

       SQL Server дополнительно поддерживает упрощенный синтаксис внешнего объединения. Чтобы выбрать перечень всех клиентов, включая тех, которые не разместили ни одного заказа, можно сделать следующее.

SELECT Customers.cust_id, Orders.order_num
FROM Customers, Orders
WHERE Customers.cust_id *= Orders.cust_id;


cust_id        order_num 
-------------  --------------------
1000000001     20005
1000000001     20009
1000000002     NULL 
1000000003     20006 
1000000004     20007 
1000000005     20008

       Здесь предложение объединения указано в предложении WHERE. Вместо проверки на равенство с помощью оператора = используется оператор *= для указания того, что в результат должна быть включена каждая строка таблицы Customers. Оператор *= представляет собой оператор левого внешнего объединения. С его помощью выбираются все строки левой таблицы.

      Противоположностью описанного левого внешнего объединения является правое внешнее объединение, его оператор таков: =*. Это объединение можно использовать для возвращения всех строк таблицы, имя которой находится справа от данного оператора, как показано в следующем примере.

SELECT Customers.cust_id, Orders.order_num
FROM Customers, Orders
WHERE Orders.cust_id =* Customers.cust_id;

      Еще одна форма внешнего объединения (используемая только в СУБД Oracle) требует использования оператора ( + ) после имени таблицы, как показано ниже.

SELECT Customers.cust_id, Orders.order_num
FROM Customers, Orders
WHERE Customers.cust_id (+) = Orders.cust_id;

 

Типы внешнего объединения

Независимо от формы используемого внешнего объединения всегда существуют только две его основные формы — левое внешнее объединение и правое внешнее объединение. Единственная разница между ними состоит в порядке указания таблиц, которые связываются. Другими словами, левое внешнее объединение может быть превращено в правое внешнее объединение просто за счет изменения порядка указания имен таблиц в предложении from или where. А раз так, то эти два типа внешнего объединения могут заменять друг друга, и решение о том, какое именно из них нужно использовать, определяется сугубо удобством выполнения операции.

      Существует и другой вариант внешнего объединения — это полное внешнее объединение, которое извлекает все строки из обеих таблиц и связывает между собой те, которые могут быть связаны. В отличие от левого внешнего и правого внешнего объединений, которые включают в результат несвязанные строки только из одной таблицы, полное внешнее объединение включает в результат несвязанные строки из обеих таблиц. Синтаксис полного внешнего объединения таков:

SELECT Customers.cust_id, Orders.order_num FROM Orders FULL OUTER JOIN Customers ON Orders.cust_id = Customers.cust_id;

 

Поддержка полного внешнего объединения

Синтаксис полного внешнего объединения не поддерживается в СУБД Access, MySQL, SQL Server и Sybase.