← Все курсы · Курс SQL · Все руководства

SQL JOIN: как соединить две таблицы без потери или удвоения строк

Каждая концепция соединения, в том порядке, в котором они дополняют друг друга · Написано для прослушивания · Часть Analyst Prep Kit

К , аналитик данных · Обновлено

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

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

Краткая версия: объединение может удалять строки, которые не нашли совпадений, и дублировать строки, которые нашли несколько. Поэтому каждый раз считайте свои ряды до и после.

Здесь одна идея решает все остальное, поэтому она и дает представление о картине. Соединение не добавляет столбцы в вашу таблицу. Он создает новую таблицу, и вам придется самостоятельно подсчитать количество ее строк.

What a join does to your row count Three games listed on the left are matched to review rows listed in the middle. The first game, Parabox, connects by a single line to one review of 12 hours, and appears once in the result column on the right. The second game, Maj'Eyal, connects by three lines to three separate reviews of 174, 96 and 310 hours, and appears three times in the result column, its name repeated on each row. The third game, Until Then, has a line that ends in a cross because no review matches it, and it does not appear in the result column at all. The result column therefore holds four rows, while neither of the two original tables had four rows. games (one row per game) reviews (one row per review) INNER JOIN result Parabox Maj'Eyal Until Then 12 hours 174 hours 96 hours 310 hours ✕ Parabox · 12 Maj'Eyal · 174 Maj'Eyal · 96 Maj'Eyal · 310 Multiplied One game with three reviews became three rows. Any SUM of a game column now counts that game three times. Dropped The game with no reviews is gone from the result. An INNER JOIN removes it. A LEFT JOIN keeps it, with the review columns empty. The result has four rows. Neither table had four rows. That change is the whole subject of this guide.
Соединение создает новую таблицу, количество строк которой не совпадает с тем, с которого вы начали.
Что вы узнаете
  1. Что на самом деле делает соединение с вашими строками
  2. Шесть типов соединений и что сохраняет каждый из них
  3. Ошибка первая: автоматическое удаление и проверка, которая его перехватывает.
  4. Ошибка вторая: молчаливое умножение и проверка, которая его ловит.
  5. Полное до и после
  6. Пограничные случаи, нарушающие соединения в реальных данных
  7. Почему это работает
  8. Использование этого в вашем собственном проекте
  9. Все на одном экране
Проработанный пример реальный. Все цифры на этой странице взяты из опубликованного портфолио проекта: списка из 175 игр, объединенных в таблицу из 41 154 794 отзывов игроков. Запросы выполняются к полным наборам данных по адресу Скрытые сокровища Пар на GitHub. Если соединения — единственное новое здесь, и такие предложения, как GROUP BY и HAVING тоже, начните с Основы SQL и вернись.

1. Что на самом деле делает соединение с вашими строками

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

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

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

Таким образом, количество выходных строк не является ни левым, ни правым. Это количество совпадающих пар, которое может быть меньше, чем любая таблица, или больше, чем обе.

Уровень детализации: идея, благодаря которой соединения имеют смысл

тот grain таблицы — это то, что означает одна строка. Скажите это вслух, прежде чем присоединиться к чему-либо.

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

Назовите уровень детализации результата, прежде чем писать совокупность. Почти каждое неправильное число, полученное в результате соединения, происходит из-за агрегирования столбца с неправильной зернистостью. Если вы можете произнести вслух «одна строка на отзыв», вы уже это знаете. SUM(price) теперь цена умножена на количество отзывов.

Каждый запрос на этой странице присваивает своим таблицам псевдонимы. FROM hidden_gems AS g означает «для оставшейся части этого запроса вызовите эту таблицу g", так g.Name столбец «Имя» hidden_gems. Двум объединенным таблицам почти всегда нужны эти псевдонимы, поскольку обе могут содержать столбец с одинаковым именем. Псевдонимы SQL и чтение запроса вслух охватывает всю привычку, если она новая.

2. Шесть типов соединений и что сохраняет каждый из них

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

Каждый тип хранит свой набор строк. Правило пары из первого раздела по-прежнему применимо ко всем из них. Все, что они меняют, — это то, что происходит со строками, которые не нашли партнера.

ТипЧто он хранитКогда ты этого захочешь
INNER JOINТолько совпадающие пары. Несовпадающие строки с обеих сторон исчезли.Когда о ссоре без партнера действительно не может быть и речи
LEFT JOINКаждый левый ряд. Правые столбцы возвращаются NULL где ничего не совпало. Безопасное значение по умолчанию. Вы сохраняете свою популяцию и можете увидеть, что не совпало.
RIGHT JOINВ каждом правом ряду та же идея в обратном порядке.Редко. Большинство людей меняют порядок таблиц и используют LEFT вместо этого, потому что читать два направления в одном запросе сложно.
FULL OUTER JOINВсё с обеих сторон, совпало или нет.Согласование двух списков, которые должны совпадать и не совпадать
CROSS JOINКаждый левый ряд в паре с каждым правым рядом. Никакого ключа вообще.Специальное создание полной сетки, например, каждый месяц пересекается с каждым регионом, чтобы пустые комбинации все еще появлялись.
Самостоятельное присоединениеНе ключевое слово. Таблица, присоединенная сама к себе под двумя разными псевдонимами.Строки, относящиеся к другим строкам в той же таблице, например, сотрудник и его руководитель.

CROSS JOIN — это ответ на вопрос, и его стоит узнать именно из-за несчастного случая. Две таблицы по 1000 строк каждая, перекрестно соединенные, дают миллион строк. Если вы когда-нибудь напишете соединение и забудете ON некоторые базы данных дают именно это, и первым признаком этого является запрос, который никогда не завершается.

Примечание к слову «внешний». LEFT, RIGHT и FULL все являются внешними соединениями, и вы увидите, что они записаны как LEFT OUTER JOIN. Слово OUTER является необязательным и означает то же самое. Аналогично, равнина JOIN без слова перед ним - это INNER JOIN, о чем стоит помнить, поскольку именно это значение по умолчанию вызывает первый сбой ниже.

Постоянно появляются еще два фрагмента синтаксиса. ON устанавливает условие соответствия, как в ON g.AppID = r.app_id. USING (app_id) это сокращение, обозначающее, что столбец имеет одно и то же имя в обеих таблицах. А когда условие соединения не является простым равенством, например, сопоставление даты с диапазоном, это неэквивалентное соединение. Он работает таким же образом и с энтузиазмом расходится веерами, так что считайте свои ряды.

3. Ошибка первая: тихое удаление

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

Равнина JOIN это INNER JOIN. Он сохраняет только строки, совпадающие с обеих сторон. Строки, не совпавшие ни с чем, не помечаются, не учитываются и не упоминаются. Они просто отсутствуют.

Для моих двух наборов данных это имело огромное значение. Две таблицы были собраны разными людьми в разное время, поэтому их охват не совпадает. Проверка того, сколько игр вообще имели соответствующий обзор:

SELECT COUNT(DISTINCT g.AppID) AS games_with_reviews
FROM games_raw AS g
JOIN recommendations AS r ON g.AppID = r.app_id;

Ответ — 36 255 из 125 855 игр, это около 29%. Примерно семь из десяти игр в левой таблице исчезнут из любого внутреннего соединения с таблицей обзора. Если ограничиться 175 играми, которые меня действительно интересовали, около 57 из них не имели обзоров. Внутреннее соединение незаметно уменьшило мою популяцию на треть, прежде чем я что-либо рассчитал, и набор результатов выглядел законченным. Столбцы были правильными, порядок был правильным, цифры были правдоподобными.

Проверка, которая ловит это

Две строки: запускайте, прежде чем доверять чему-либо нижестоящему. Во-первых, сколько строк вошло. Во-вторых, сколько разных ключей получилось.

SELECT COUNT(*) AS rows_in FROM hidden_gems;

SELECT COUNT(DISTINCT g.AppID) AS keys_out
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id;

если keys_out меньше, чем rows_in, ваше присоединение теряет записи, и теперь вам нужно принять решение, а не случайно узнать об этом позже. Либо дроп в порядке и вы об этом письменно говорите, либо нет и вы переходите на дроп. LEFT JOIN.

Запишите коэффициент совпадения в любом случае. «Анализ игрового времени охватывает 118 из 175 игр, или 67%, поскольку набор данных обзора не включает остальные» — это предложение, которое заставляет рецензента доверять всему документу. Если оставить это в стороне, они перестанут ему доверять.

Анти-соединение и почему пустой столбец — это находка

A LEFT JOIN сохраняет каждую строку из левой таблицы независимо от того, совпала она или нет, заполняя правую часть NULL. Это дает вам возможность задать вопрос, на который не может ответить внутреннее соединение: какие строки ничего не нашли? Сохраните все, а затем оставьте только те, правая сторона которых оказалась пустой. Этот шаблон называется запрет на присоединениеи это постоянно проявляется в интервью.

SELECT g.Name, g.pct_positive
FROM hidden_gems AS g
LEFT JOIN recommendations AS r ON g.AppID = r.app_id
WHERE r.app_id IS NULL
ORDER BY g.pct_positive DESC;

Прочтите WHERE внимательно, потому что это та часть, которая удивляет людей. r.app_id IS NULL не может быть истинным для любой совпавшей строки, поскольку совпавшая строка имеет там реальное значение. Это справедливо только для строк LEFT JOIN изобретен, чтобы сохранить непревзойденный левый ряд. Таким образом, фильтр означает «сохранить строки, которые ничего не нашли».

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

Ничего из этого не существовало бы во внутреннем соединении. Пустой столбец – это не дыра в вашей работе. Часто это самый интересный результат, который у вас есть, и он должен быть в вашей рецензии: Документирование ограничений данных рассказывает о том, как.

4. Ошибка вторая: молчаливое умножение

Перед пояснением: у одного покупателя три заказа. Вы присоединяете клиентов к заказам, а затем суммируете столбец, который относится к клиенту, например, его кредитный лимит. Какая цифра выходит, и почему это не кредитный лимит?

Когда к таблице обзоров присоединяется игра с 2498 отзывами, в этой игре становится 2498 строк. Его название повторяется 2498 раз. Его цена повторяется 2498 раз. Это называется Разветвление, и проблемы начинаются в тот момент, когда вы объединяете столбец, полученный со стороны одной строки на игру.

Вот неправильный запрос. Это выглядит вполне разумно.

SELECT g.Name, SUM(g.Price) AS total_price
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id
GROUP BY g.AppID, g.Name;

По моим данным, для одной игры по цене 3,49 доллара США с 2498 совпадающими отзывами это SUM возвращает 8718,02. Цена игры по-прежнему составляет $3,49. Запрос добавлял ее один раз за проверку, поскольку после объединения имеется 2498 строк, содержащих эту цену. Никаких ошибок, никаких предупреждений, а в столбце «Общая цена» находится число примерно в 2500 раз больше.

Объединять только столбцы, полученные со стороны многих. Колонны с одной стороны принадлежат GROUP BY, никогда в SUM. В этом объединении hours и review_id находятся на стороне многих, поэтому их подсчет и усреднение корректны. Name и Price находятся на одной стороне, поэтому они группируются.

Средние значения скрывают это лучше, чем суммы, что делает их более опасными. AVG(g.Price) по 2498 повторяющимся строкам возвращается 3,49 доллара, правильный ответ, поэтому все выглядит не так. Затем тот же образец встречается с игрой с двумя строками во второй объединенной таблице. Дублирование перестает быть равномерным, и среднее значение незаметно начинает придавать некоторым записям больший вес, чем другим. Прежде чем читать дальше, скажите вслух, почему неравномерное дублирование нарушает средний показатель, а даже дублирование — нет. Это основа всего руководства.

Проверка, которая ловит это

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

SELECT COUNT(*) AS joined_rows,
       COUNT(DISTINCT g.AppID) AS distinct_games
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id;

если joined_rows намного больше, чем distinct_games, объединение расширило вашу таблицу, и это совершенно нормально, если вы это имели в виду. Разветвление не является ошибкой. Для этого и нужно соединение «один-ко-многим». Это становится ошибкой только тогда, когда вы суммируете, как будто этого не произошло.

Другая половина исправления HAVING. После группировки фильтр по агрегату должен выполняться после группировки, что и является HAVING делает и WHERE не могу.

SELECT g.Name,
       g.Price,
       COUNT(r.review_id) AS num_reviews,
       ROUND(AVG(r.hours), 1) AS avg_hours
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id
GROUP BY g.AppID, g.Name, g.Price
HAVING COUNT(r.review_id) >= 50
ORDER BY avg_hours DESC;

Этот 50-й этаж значит больше, чем кажется. Без этого игра с тремя обзорами и одним навязчивым игроком превосходит все остальное. Благодаря этому на вершине моего списка оказались игры, у которых сотни или тысячи обзоров отстают от среднего показателя, что и отличает находку от артефакта. Подробнее о том, как честно выбрать это число, читайте в Пороги, управляемые данными.

5. Полное до и после

Те же две таблицы, тот же вопрос. Первая версия работает и лежит. Второй работает, говорит правду и излагает собственное освещение.

До

SELECT g.Name,
       SUM(g.Price) AS total_price,
       AVG(r.hours) AS avg_hours
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id
GROUP BY g.AppID, g.Name
ORDER BY avg_hours DESC;

Три проблемы, ни одна из которых не приводит к ошибке. SUM(g.Price) умножается на количество отзывов. Внутреннее объединение удалило все игры без обзоров, не говоря уже о них. А без минимального количества обзоров игра с двумя отзывами может возглавить рейтинг.

после

-- ============================================================
-- STEP 6: Which games do players actually keep playing?
-- WHY: A high rating says people liked it once. Average hours
--      says they stayed. Joining the game list to real playtime
--      is the only way to tell those apart. The 50-review floor
--      keeps a single obsessive player from topping the chart.
-- COVERAGE: 118 of 175 games matched the review data (67%).
--      The 57 unmatched games are listed separately, not dropped.
-- ============================================================
--SELECT the game name, its price, how many reviews matched,
--   and the average hours those reviewers played:
--   COUNT(r.review_id) = number of matched review rows per game
--   AVG(r.hours)       = mean hours across those reviews
--   ROUND(..., 1)      = round to one decimal place
--FROM the hidden_gems list (g), joined to reviews (r) on the game id
--GROUP BY the game, so each game collapses to one row
--HAVING at least 50 matched reviews, so the average is trustworthy
--ORDER BY average hours, highest first
SELECT g.Name,
       g.Price,
       COUNT(r.review_id) AS num_reviews,
       ROUND(AVG(r.hours), 1) AS avg_hours
FROM hidden_gems AS g
JOIN recommendations AS r ON g.AppID = r.app_id
GROUP BY g.AppID, g.Name, g.Price
HAVING COUNT(r.review_id) >= 50
ORDER BY avg_hours DESC;

Столбец цен сгруппирован, а не суммирован, поэтому он остается равным 3,49 доллара. В строке покрытия указано, что было удалено в результате объединения, чтобы читатель знал масштаб. Нижний этаж не позволяет ранжированию определяться выборкой из двух человек. Формат комментариев тот же, что и у Как комментировать SQL, чтобы он обучал.

Теперь представьте себе последнее объединение, которое вы написали для своих собственных данных. Какая из этих трех проблем, скорее всего, уже присутствует в нем и что вам скажет подсчет строк?

6. Пограничные случаи, нарушающие соединения в реальных данных

Перед объяснением: соединение возвращает ноль строк. Не мало. Ноль. Обе таблицы заполнены, и идентификаторы на экране выглядят одинаково. Что бы вы проверили в первую очередь?

Семь вещей, каждая из которых кого-то остановила на целый день.

Ключевые столбцы называются по-другому. games_raw.AppID и recommendations.app_id — это одно и то же число из одного и того же источника, написанное двумя способами, поскольку наборы данных создавали два человека. Важно то, что они имеют один и тот же идентификатор, а не то, что у них общее имя.

Ключевые столбцы имеют разные типы. Это ответ на предварительный вопрос. Идентификатор, хранящийся в виде текста в одной таблице, и число в другой вообще ничему не соответствуют, и в результате получается пустая таблица, а не ошибка. Если соединение возвращает ноль строк, а вы ожидали тысячи, прежде всего проверьте типы.

Логическое значение сохраняется в виде текста. В обзорной таблице is_recommended содержит текст в нижнем регистре 'true' и 'false', а не 1 и 0. Фильтрация включена is_recommended = 1 ничего не соответствует и возвращает нулевое значение, что воспринимается как реальный ответ.

NULL в ключе соединения. A NULL ключ никогда не соответствует ничему, включая другой NULL, потому что NULL означает неизвестное, а не пустое. Строки с отсутствующим ключом выпадают из внутреннего соединения без слов. Сначала посчитайте их с помощью SELECT COUNT(*) FROM t WHERE key_column IS NULL.

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

Соединение происходит медленно, потому что одна сторона огромна. Сопоставление 125 855 строк с 41 миллионом требует серьезной работы. Индекс ключевого столбца большой таблицы превращает полное сканирование в поиск: CREATE INDEX idx_rec_appid ON recommendations(app_id);. Создайте его один раз, и каждое последующее соединение будет быстрым. Обработка больших наборов данных охватывает остальную часть работы в этом размере.

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

Почему это работает

Описанное выше поведение не является особенностью реализации одной базы данных. Это выходит за рамки того, как реляционная модель определяет операцию. Исходная формулировка Кодда определяет соединение как производное отношение, построенное из пар строк, удовлетворяющих условию сопоставления (Кодд, 1970, Коммуникации ACM, 13(6), 377–387). Как только результат определен как набор совпадающих пар, оба поведения становятся обязательными. Ряд без партнера не дает пары, а ряд с несколькими партнерами дает несколько. Удаление и умножение не являются крайними случаями, находящимися поверх соединений. Они и есть то, что такое соединение.

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

Есть и вторая причина, по которой эта страница постоянно просит вас произносить слова вслух, а не просто читать их. Учащиеся, которые объясняют себе проработанный пример по ходу дела, понимают его значительно лучше и лучше переносят его на новые задачи, чем учащиеся, которые читают тот же пример, не объясняя его (Чи, Басок, Льюис, Рейманн & Глейзер, 1989, Когнитивная наука, 13(2), 145–182). Соединения — это то, где это окупается больше всего, потому что ошибка никогда не бывает в ключевом слове. Это то, что, по вашему мнению, означает одна строка.

Использование этого в вашем собственном проекте

Подумайте о запросе, который вы уже написали и отправили. Можете ли вы прямо сейчас сказать, что означает одна строка его результата и является ли это тем же самым, что означала одна строка до объединения? Если это занимает больше нескольких секунд, этот запрос следует проверить в первую очередь.

Аудит каждого соединения в существующем проекте одновременно — мрачная работа, и вы остановитесь на полпути. Вместо этого сделайте это по порядку.

  1. Произнесите вслух суть обеих таблиц. прежде чем писать соединение. «Одна строка на каждого клиента» и «Одна строка на заказ». Десять секунд, и он предсказывает форму результата.
  2. Проведите два счета. Строки вводятся по отдельным ключам для проверки на отбрасывание. Общее количество строк по отдельным ключам для проверки умножения. Два запроса.
  3. Запишите коэффициент совпадения в файл в качестве комментария в том же проходе. Не позже. Позже никогда не бывает, и рецензент спрашивает об этом числе в первую очередь.
  4. Проверьте каждый агрегат на соответствие зерну. Все, что с одной стороны, входит GROUP BY. Все, что касается многих, можно посчитать или усреднить. Проходите их по одному.
  5. Запустите анти-соединение один раз, даже если вы планируете использовать внутреннее соединение. Если в несовпадающих строках есть закономерность, эта закономерность является выводом о ваших данных, и вам лучше изучить ее сейчас, чем при просмотре.

Если вы начинаете с нуля, а не проводите аудит, выполните первый и второй шаги, прежде чем писать настоящий запрос. Соединение, количество строк которого вы уже предсказали, — это соединение, которое не может вас удивить.

Если у вас под рукой есть бумага и свободные пять минут, стоит сделать один рисунок, и он не является обязательным. Нарисуйте три ряда слева, четыре справа, соедините их так, как показано на картинке вверху, и сами посчитайте выходные ряды. На этой концепции основано все остальное, и рисование ее по памяти — это одновременно и попытка восстановления, и проверка того, действительно ли она у вас есть.

Подробнее об этом и еще что-нибудь подобное. Все инструкции находятся в одном месте на индекс направляющих: SQL, Tableau, миграция данных и связанные с ними рабочие привычки.

Все на одном экране

Это лист поиска. Закройте правую колонку, проработайте левую и произнесите каждый ответ вслух, прежде чем проверять его.

концепцияЧто он делает
Правило парыДля каждой левой строки найдите каждую совпадающую правую строку и напишите по одной выходной строке для каждой пары.
GrainЧто означает одна строка. Зернистостью результата соединения обычно является множественная сторона.
Простой JOINАн INNER JOIN. Это значение по умолчанию вызывает автоматическое удаление.
INNER JOINТолько совпадающие пары. Несовпадающие строки с обеих сторон исчезли.
LEFT JOINКаждый левый ряд сохранен. Правые столбцы NULL где ничего не совпало.
RIGHT JOINКаждый правый ряд сохранен. Обычно переписывается как LEFT JOIN с заменой столов.
FULL OUTER JOINНесовпадающие ряды сохранены с обеих сторон.
CROSS JOINКаждый левый ряд в паре с каждым правым рядом. Нет ключа. 1000 на 1000 — это миллион строк.
Самостоятельное присоединениеТаблица, присоединенная сама к себе под двумя псевдонимами. Сотрудники и менеджеры.
запрет на присоединениеLEFT JOIN плюс WHERE right.key IS NULL. Перечисляет строки, в которых ничего не найдено.
Тихое удалениеНесовпадающие строки исчезают из внутреннего соединения без ошибок.
Проверьте этоГребет против COUNT(DISTINCT key) вне.
РазветвлениеОдна строка, совпадающая со многими, становится множеством строк, повторяя значения одной стороны.
Проверьте этоCOUNT(*) против COUNT(DISTINCT key) в объединенном результате.
Агрегатное правилоМногосторонние столбцы можно суммировать или усреднять. Входят односторонние колонны GROUP BY.
WHERE против HAVINGWHERE фильтрует строки перед группировкой. HAVING фильтрует группы после и является единственным, кто видит агрегат.
Соединение возвращает ноль строкОбычно несовпадение типа на ключе. Проверьте сохраненный тип с обеих сторон.
NULL в ключеНикогда не совпадает ни с чем, включая другое NULL. Эти строки исчезают бесшумно.
Присоединение «многие ко многим»Три левых и четыре правых становятся двенадцатью. Сначала агрегируйте одну сторону в одну строку для каждого ключа.
Медленное присоединениеБольшая сторона сканируется полностью. Индексируйте ключевой столбец.
Коэффициент соответствияДоля вашего населения, пережившая присоединение. Записывайте это в файл каждый раз.
Единственная привычка, которую следует сохранить. Если вы больше ничего не берете с этой страницы, подсчитайте свои строки до и после каждого соединения и запишите коэффициент соответствия. Обе ошибки здесь невидимы в тексте запроса и очевидны в количестве строк. Если соединение идет не так, как описано на этой странице, существует общая ошибка. шлейф диагностики на предмет застревания.

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

Ссылки

Соединение прошло успешно, а количество строк увеличилось, что означает, что что-то совпало дважды.

SQL для аналитиков составляет 458 страниц, каждое объединение читается построчно, а количество строк печатается до и после.

SQL для аналитиков, 19 $ →
Практика соединяется с данными, которые находятся перед вами.

Лестница соединений в SQL-практикум — это тринадцать запросов к наполовину перенесенной клиентской системе: сопоставьте две стороны, найдите шесть клиентов, которые так и не появились, посмотрите, как таблица «один ко многим» превращает 40 клиентов в 78 строк, а затем исправляете это. Каждый запрос выполняется в браузере. Ничего устанавливать, учетная запись не требуется.

Просверлите лестницу соединений →

Предпочитаете проработанные примеры, карточки и пробный экзамен? Курс SQL также есть ПРИСОЕДИНЯЙТЕСЬ к лаборатории.