Далее рассмотрим принцип работы левого внешнего объединения. Проанализируем следующий SQL-запрос.
Листинг 10.18.
SELECT * FROM users LEFT JOIN users_groups ON users.uid = users_groups.uid;
По-русски это можно перевести так: "Выбрать все строки с левой стороны объединения (таблица users) и для каждой выбранной строки отобразить соответствующее ей значение из правой части (таблица users_groups), если оно существует (значение, удовлетворяющее ограничениям предложения ON или USING), или отобразить строку со значениями NULL, если соответствия нет". Этот тип объединения называется левым объединением или левым внешним объединением.
В результате мы получаем следующий результат.
Левое внешнее объединение
9 rows in set (0.05 sec)
Как видим, все записи из левой части объединения (таблица users) присутствуют в окончательном результирующем наборе. Отображаются те записи, которые имеют соот­ветствующее значение в правой части (принадлежность к группе), а отсутствующие значения обозначаются как NULL.
Этот тип объединения очень полезен, когда необходимо определить, каким значениям из одной таблицы ничего не соответствует в другой. Для этого достаточно просмотреть строки со значениями NULL. Беглого взгляда на предыдущий пример достаточно, чтобы убедиться в том, что напротив пользователей harry и mark нет соответствующих им записей в таблице users_groups.
В действительности такой просмотр выводимых данных не нужен. Эта задача возлагается на язык SQL. Для этого просто добавим предложение WHERE.
Левое внешнее объединение
Правое внешнее объединение

Вполне понятно существует и правое внешнее объединение, которое предназначено для выполнения тех же задач, что и левое, но в обратном порядке. Рассмотрим следующий запрос и результирующий набор, полученный с его помощью.
Левое внешнее объединение
Левое внешнее объединение
По-русски это можно перевести как "выбрать все строки с правой стороны объединения (таблица groups) и для каждой выбранной строки отобразить соответствующее значение из левой части (таблица users_groups), если оно существует (значение, удовлетворяющее ограничениям предложения ON или USING), или отобразить строку со значениями NULL".

Естественный порядок
При выполнении объединения, MySQL создает результирующий набор, соединяя таблицы и используя условное выражение, заданное в предложении ON или USING. Кроме того, MySQL "решает", какие записи попадают в этот результирующий набор, после использования условного выражения, заданного предложением WHERE.
Поэтому необходимо тщательно продумать, где именно должны появляться ограничения в строке запроса. Перенос ограничения из предложения WHERE в предложение ON меняет смысл запроса, а значит, и его результат. Некоторые записи, которые в противном случае никогда не попадают в результирующий набор, могут быть представлены не NULL-значениями на одной стороне и значениями NULL в другой.
Обычно предложения ON и USING не используются для удаления ненужных записей и формирования окончательного результирующего набора. Для этого по-прежнему лучше всего подходит предложение WHERE.
Таким образом, что касается предыдущего правого внешнего объединения, в окончательный результирующий набор попадают все группы. У тех из них, к которым относится определенное число пользователей (т.е. имеется соответствующее значение в левой стороне в таблице users_groups), отображается это значение. Остальные имеют значение NULL.
Левое внешнее объединение
Еще несколько примеров
Предположим, что требуется определить, в какие группы входят по два и более пользователя. Это можно сделать путем создания правого объединения. Для этого достаточно сгруппировать записи по полю gid, а потом подсчитать их с помощью функции COUNT().
Левое внешнее объединение
Точка зрения
Термины "левое объединение" и "правое объединение" являются взаимозаменяемыми и зависят от точки зрения. Левое объединение может быть преобразовано в правое (и наоборот) путем простой замены порядка следования таблиц в объединении. Рассмотрим следующие два запроса:
SELECT * FROM c LEFT JOIN a USING (id); SELECT * FROM a RIGHT JOIN c USING (id);
В переводе на русский язык это означает следующее: "Выберите все строки из таблицы с и для всех выбранных строк отобразите соответствующее значение из таблицы a или значение NULL".
А как получить общее количество пользователей в каждой группе? Это сделать довольно просто - обычный запрос SELECT с предложением GROUP BY.
Левое внешнее объединение
А как можно определить пользователей, не представленных ни в одной из групп? Попытаемся это сделать с помощью следующего запроса.
Левое внешнее объединение
Это очень хороший пример использования проверки IS NULL вместе с объединением с целью проверить данные на разрушение. В этом случае каждая запись из таблицы us-ers_groups (правая сторона объединения) сравнивается с записями таблицы users для определения их соответствия. Результирующий набор содержит два значения NULL, отражая тем самым, что некоторые группы были присвоены несуществующим пользователям, а это говорит о возможном разрушении данных.