Соединения SQL: краткий пример

Понять, почему и как выполняются соединения SQL

Изначально это сообщение в блоге было задумано как примечание к моему сообщению Pandas Join vs. Merge. Но он оказался достаточно длинным, чтобы оправдать отдельный пост (и слишком подробным для примечания). Это не должно быть исчерпывающим учебным пособием по SQL-соединениям, а скорее примером, который поможет новичкам в SQL и реляционных базах данных начать понимать, что означает объединение двух таблиц.

Почему мы присоединяемся?

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

Реляционные базы данных предназначены для объединения. Каждая таблица в базе данных содержит данные определенной формы или функции. Например, одна таблица может содержать основные данные о клиентах компании, такие как идентификатор клиента (уникальный идентификатор, который может использоваться для идентификации каждого клиента), имя , возраст, пол, дата первой покупки и адрес. В отдельной таблице гораздо большего размера хранятся подробные данные уровня транзакции - идентификатор транзакции, дата транзакции, идентификатор клиента, категория продукта, идентификатор продукта, проданные единицы и цена.

У данного клиента (или идентификатора клиента) могут быть сотни или даже тысячи транзакций, поэтому было бы крайне избыточно хранить основную информацию этого клиента снова и снова для каждой строки в таблице транзакций. Таблица транзакций должна быть только для данных, относящихся к транзакциям. Слишком много перекрывающихся данных между таблицами расточительно и может отрицательно сказаться на производительности системы.

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

Как мы присоединяемся?

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

SELECT * FROM Employee
SELECT * FROM Sale

(Я опустил подчеркивание в именах столбцов на рисунках для удобства чтения)

Теперь давайте присоединимся к двум столам. Чтобы связать две таблицы, нам нужно выбрать столбец (или комбинацию столбцов), который служит точкой пересечения - давайте назовем выбранный столбец индексом объединения. Записи таблицы, которые имеют одно и то же значение для индекса объединения, объединяются. Обратите внимание, что пересечение не обязательно должно быть один к одному. Например, Тони совершил 2 продажи, поэтому после присоединения к столам обе его продажи будут связаны с Тони (он же идентификатор сотрудника 1).

Когда мы объединяем таблицы, мы обычно хотим, чтобы индекс соединения был уникальным. Если бы индекс соединения не был уникальным, могли бы возникнуть необычные вещи. Например, предположим, что у нас был второй сотрудник по имени Тони (вместе с таблицами ниже), и он был продавцом мегазвезды. Если бы вместо того, чтобы присоединиться к «Идентификатору сотрудника», мы присоединились бы к «Имени», то мы бы ошибочно связали продажи Тони Мегазвезды со мной, что сделало бы мой бонус слишком высоким:

И Тони Мегазвезда тоже получит признание за мои жалкие продажи (не то чтобы ему это было нужно). Чтобы избежать этого, мы объединяем столбец с уникальными значениями, такими как «Идентификатор сотрудника» (я удалил Тони Мегазвезда, поскольку он был там только для того, чтобы проиллюстрировать, чего не следует делать, и его невероятные успехи заставили меня почувствовать себя недостойным):

Существуют различные типы SQL-соединений, и я не буду вдаваться в подробности их здесь. В этом примере мы будем использовать левое соединение, что означает, что мы отдаем приоритет строкам в левой таблице. Таким образом, наш вывод будет включать каждую строку в левой таблице (с «Имя» и «Заголовок») независимо от того, есть ли совпадение с правой таблицей - таким образом, сотрудники, которые не совершили продажу в нашем выводе по-прежнему будет строка, но не будет никаких значений (точнее NULL) для столбцов «Номер продажи» и «Продано единиц».

Давайте посмотрим на наш результат (мы выбираем только «Номер продажи» и «Проданные единицы» из правой таблицы и сортируем по «Идентификатору сотрудника»):

SELECT e.*, s.Sale_Number, s.Units_Sold
FROM Employee as e
    LEFT JOIN Sale as s ON e.Employee_ID=s.Employee_ID
ORDER BY e.Employee_ID

Результат нашего соединения теперь включает данные из обеих таблиц. Данные о продажах Тони были связаны с данными его сотрудников (благодаря идентификатору сотрудника), как и данные Лизы. Обратите внимание на 2 вещи:

  1. Это выглядит немного повторяющимся, потому что «ID сотрудника», «Имя» и «Должность» повторяются столько раз, сколько у сотрудника есть продажи. На самом деле мы не будем останавливаться на достигнутом. Затем мы, скорее всего, создадим группировку по, чтобы подсчитать, сколько продаж сделал каждый сотрудник, или вычислить среднее количество единиц, проданных каждый раз, когда сотрудник совершает продажу.
  2. Идентификатор сотрудника 3 отсутствует в выходных данных, потому что мы выполнили левое соединение и в левой таблице не было записи для идентификатора сотрудника 3. Таким образом, он был опущен.

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

Ключевые выводы:

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