0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Реляционная модель подразумевает связь между данными разных отношений посредством внешних ключей. С практической точки зрения это можно сформулировать так - зная первичный ключ одной сущности, мы можем извлечь связанные с ней данные из другой сущности.</p>
1
<p>Реляционная модель подразумевает связь между данными разных отношений посредством внешних ключей. С практической точки зрения это можно сформулировать так - зная первичный ключ одной сущности, мы можем извлечь связанные с ней данные из другой сущности.</p>
2
<p>В простых ситуациях данные извлекаются так:</p>
2
<p>В простых ситуациях данные извлекаются так:</p>
3
<p>Но есть множество ситуаций, где простой выборкой не обойтись. Для этого нужна операция JOIN, которую мы изучим в этом уроке.</p>
3
<p>Но есть множество ситуаций, где простой выборкой не обойтись. Для этого нужна операция JOIN, которую мы изучим в этом уроке.</p>
4
<h2>JOIN</h2>
4
<h2>JOIN</h2>
5
<p>Для примера попробуем найти всех пользователей Хекслета, которые ни разу не создавали топики. На текущий момент мы знаем ровно один способ выполнить эту задачу. Нужно выполнить два шага:</p>
5
<p>Для примера попробуем найти всех пользователей Хекслета, которые ни разу не создавали топики. На текущий момент мы знаем ровно один способ выполнить эту задачу. Нужно выполнить два шага:</p>
6
<ol><li><p>Извлечь из базы всех пользователей, которые создали хотя бы один топик:</p>
6
<ol><li><p>Извлечь из базы всех пользователей, которые создали хотя бы один топик:</p>
7
</li>
7
</li>
8
<li><p>Найти всех пользователей, у которых идентификаторы не совпадают со списком user_id, полученном на предыдущем этапе:</p>
8
<li><p>Найти всех пользователей, у которых идентификаторы не совпадают со списком user_id, полученном на предыдущем этапе:</p>
9
</li>
9
</li>
10
</ol><p>Задача будет решена, но есть одна проблема. Идентификаторов может быть очень много. Гонять такое количество записей из базы в код и обратно - не самая разумная идея.</p>
10
</ol><p>Задача будет решена, но есть одна проблема. Идентификаторов может быть очень много. Гонять такое количество записей из базы в код и обратно - не самая разумная идея.</p>
11
<h2>INNER JOIN</h2>
11
<h2>INNER JOIN</h2>
12
<p>Теперь рассмотрим следующую задачу - найти записи о пользователях в одной таблице, для которых нет записей о топиках в другой таблице.</p>
12
<p>Теперь рассмотрим следующую задачу - найти записи о пользователях в одной таблице, для которых нет записей о топиках в другой таблице.</p>
13
<p>Реляционная алгебра позволяет выполнить эту операцию с помощью соединения JOIN, используя ровно один запрос. Начнем знакомство с JOIN на таком примере, в котором мы найдем имена всех пользователей, создавших хотя бы один топик</p>
13
<p>Реляционная алгебра позволяет выполнить эту операцию с помощью соединения JOIN, используя ровно один запрос. Начнем знакомство с JOIN на таком примере, в котором мы найдем имена всех пользователей, создавших хотя бы один топик</p>
14
<p>Результатом такого запроса станет выборка, в которую попали поля обеих таблиц. Здесь соединяются две таблицы: users и topics по условию users.id = topics.user_id. Это важное условие для правильной работы.</p>
14
<p>Результатом такого запроса станет выборка, в которую попали поля обеих таблиц. Здесь соединяются две таблицы: users и topics по условию users.id = topics.user_id. Это важное условие для правильной работы.</p>
15
<p>В нашем примере отношения связаны внешним ключом: соответственно, при объединении этих таблиц нужно явно указать, как мы их соединяем. Общий синтаксис выглядит так:</p>
15
<p>В нашем примере отношения связаны внешним ключом: соответственно, при объединении этих таблиц нужно явно указать, как мы их соединяем. Общий синтаксис выглядит так:</p>
16
<p>На самом деле общая форма сложнее, потому что объединять можно произвольное число таблиц. Другими словами, условий соединения может быть много.</p>
16
<p>На самом деле общая форма сложнее, потому что объединять можно произвольное число таблиц. Другими словами, условий соединения может быть много.</p>
17
<p>JOIN - это сокращенная версия соединения INNER JOIN, то есть внутреннего соединения.</p>
17
<p>JOIN - это сокращенная версия соединения INNER JOIN, то есть внутреннего соединения.</p>
18
<p>В эту выборку попадают только те записи, для которых есть соответствие в другой таблице. Причем, если у одного пользователя пять топиков, то в выборке окажутся все пять строк. Такой запрос имеет смысл делать на странице вывода топиков, что позволит к каждому топику сразу же вывести нужную информацию и о самом пользователе.</p>
18
<p>В эту выборку попадают только те записи, для которых есть соответствие в другой таблице. Причем, если у одного пользователя пять топиков, то в выборке окажутся все пять строк. Такой запрос имеет смысл делать на странице вывода топиков, что позволит к каждому топику сразу же вывести нужную информацию и о самом пользователе.</p>
19
<p>Запросы с соединениями порождают одну небольшую проблему. В примере выше часть SELECT содержит только те поля, имена которых уникальны среди всех полей обеих таблиц. Соответственно, при выборке не возникает неоднозначностей.</p>
19
<p>Запросы с соединениями порождают одну небольшую проблему. В примере выше часть SELECT содержит только те поля, имена которых уникальны среди всех полей обеих таблиц. Соответственно, при выборке не возникает неоднозначностей.</p>
20
<p>Если выполнить этот же запрос со звездочкой, то в выборку попадут поля, у которых одинаковые названия, что создаст сложности при анализе данных уже в коде приложения. А при выполнении запроса с указанием дублирующихся полей вообще возникнет ошибка:</p>
20
<p>Если выполнить этот же запрос со звездочкой, то в выборку попадут поля, у которых одинаковые названия, что создаст сложности при анализе данных уже в коде приложения. А при выполнении запроса с указанием дублирующихся полей вообще возникнет ошибка:</p>
21
<p>В таких случаях спасают псевдонимы и возможность указывать таблицу для каждого поля:</p>
21
<p>В таких случаях спасают псевдонимы и возможность указывать таблицу для каждого поля:</p>
22
<h2>LEFT JOIN</h2>
22
<h2>LEFT JOIN</h2>
23
<p>Пока мы все еще не можем решить нашу исходную задачу. Для этого понадобится операция левого соединения LEFT JOIN:</p>
23
<p>Пока мы все еще не можем решить нашу исходную задачу. Для этого понадобится операция левого соединения LEFT JOIN:</p>
24
<p>LEFT JOIN берет все данные из одной таблицы и присоединяет к ним данные из другой, если они присутствуют. Если нет, то заполняет их NULL. Чисто технически этот запрос отличается только тем, что добавляется слово LEFT:</p>
24
<p>LEFT JOIN берет все данные из одной таблицы и присоединяет к ним данные из другой, если они присутствуют. Если нет, то заполняет их NULL. Чисто технически этот запрос отличается только тем, что добавляется слово LEFT:</p>
25
<p>LEFT JOIN полезен, когда нам нужно работать со всеми данными одной таблицы и связанными с ними записями, если они есть. Если их нет, то ничего страшного, мы все равно хотим получить данные из первой таблицы.</p>
25
<p>LEFT JOIN полезен, когда нам нужно работать со всеми данными одной таблицы и связанными с ними записями, если они есть. Если их нет, то ничего страшного, мы все равно хотим получить данные из первой таблицы.</p>
26
<p>Этот запрос все еще не возвращает нам то, что мы хотели изначально - записи о пользователях, которые не оставили ни одного топика на Хекслете. Чтобы закончить решение, нужно добавить в выборку условие WHERE:</p>
26
<p>Этот запрос все еще не возвращает нам то, что мы хотели изначально - записи о пользователях, которые не оставили ни одного топика на Хекслете. Чтобы закончить решение, нужно добавить в выборку условие WHERE:</p>
27
<p>Запросы на соединение могут быть как очень простыми, так и очень сложными. Они могут занимать несколько экранов текста и включать в себя сразу множество таблиц. В этом уроке мы лишь немного затронули эту тему и познакомились с самой концепцией, остальное познается во время экспериментов в рабочих и тестовых проектах.</p>
27
<p>Запросы на соединение могут быть как очень простыми, так и очень сложными. Они могут занимать несколько экранов текста и включать в себя сразу множество таблиц. В этом уроке мы лишь немного затронули эту тему и познакомились с самой концепцией, остальное познается во время экспериментов в рабочих и тестовых проектах.</p>