Внутреннее и внешнее объединения таблиц
Предположим, необходимо узнать, какие темы, и какими авторами были созданы. Для этого проще всего обратиться к таблице «Темы (topics)»:
Пусть необходимо, чтобы в ответе на запрос были не идентификаторы авторов, а их имена? Вложенные запросы не помогут, т.к. в конечном итоге они выдают данные из одной таблицы, а в данном случае надо получить данные из двух таблиц (Темы и Пользователи) и объединить их в одну. Запросы, которые позволяют это сделать, в SQL называются Объединениями. Синтаксис самого простого объединения следующий:
SELECT имена_столбцов_таблицы_1, имена_столбцов_таблицы_2 FROM имя_таблицы_1, имя_таблицы_2;
Создадим простое объединение:
Такое объединение называется декартовым произведением, когда каждой строке первой таблицы ставится в соответствие каждая строка второй таблицы. Бывают случаи, когда такое объединение полезно, но оно не удовлетворяет постановке задачи. Чтобы результирующая таблица выглядела так, как необходимо, нужно указать условие объединения: связь таблиц по идентификатору автора. Т.е. укажем в запросе, что необходимо выводить только те строки, в которых значения поля id_author таблицы topics совпадают со значениями поля id_user таблицы users:
На схеме будет понятнее:
Т.е. в запросе было сделано следующее условие: если в обеих таблицах есть одинаковые идентификаторы, то строки с этим идентификатором необходимо объединить в одну результирующую строку.
Следует обратить внимание на две вещи:
1. Если в одной из объединяемых таблиц есть строка с идентификатором, которого нет в другой объединяемой таблице, то в результирующей таблице строки с таким идентификатором не будет. В данном примере есть пользователь Oleg (id = 5), но он не создавал тем, поэтому в результате запроса его нет.
|
2. При указании условия название столбца пишется после названия таблицы, в которой этот столбец находится (через точку). Это сделано во избежание путаницы, ведь столбцы в разных таблицах могут иметь одинаковые названия, и MySQL может не понять, о каких конкретно столбцах идет речь.
Вообще, корректный синтаксис объединения с условием выглядит так:
SELECT имя_таблицы_1.имя_столбца1_таблицы_1,
имя_таблицы_1.имя_столбца2_таблицы_1,
имя_таблицы_2.имя_столбца1_таблицы_2,
имя_таблицы_2.имя_столбца2_таблицы_2
FROM имя_таблицы_1, имя_таблицы_2
WHERE имя_таблицы_1.имя_столбца_по_которому_объединяем = имя_таблицы_2.имя_столбца_по_которому_объединяем;
Если имя столбца уникально, то название таблицы можно опустить (как сделано в примере), но делать это не рекомендуется.
Объединения дают возможность выбирать любую информацию из любых таблиц, причем объединяемых таблиц может быть и три, и четыре, да и условие для объединения может быть не одно.
Для примера создадим запрос, который покажет все сообщения, к каким темам они относятся и авторов этих сообщений. Вся эта информация хранится в таблице Сообщения (posts):
Чтобы вместо идентификаторов отображались имена и названия, необходимо сделать объединение трех таблиц:
Таблицы Сообщения и Пользователи объединены условием posts.id_author=users.id_user, а таблицы Сообщения и Темы – условием posts.id_topic=topics.id_topic.
Такие объединения называются Внутренними объединениями. Они связывают строки одной таблицы со строками другой таблицы (а может еще и третьей таблицы). Но бывают ситуации, когда необходимо, чтобы в результат были включены строки, не имеющие связанных. Например, когда был создан запрос, какие темы и какими авторами были созданы, пользователь Oleg в результирующую таблицу не попал, т.к. тем не создавал, а потому и связанной строки в объединяемой таблице не имел. Поэтому, если потребуется составить несколько иной запрос – вывести всех пользователей и темы, которые они создавали, если таковые имеются – то придется воспользоваться Внешним объединением, позволяющим выводить все строки одной таблицы и имеющиеся связанные с ними строки из другой таблицы.
|