JOIN в SQL: особенности работы с дублями

ДУБЛИ ПРИ РАБОТЕ С JOIN

Когда спрашивают, как работает соединение при использовании LEFT JOIN, многие могут ответить, что это присоединение к левой таблице. Но это не совсем так. 

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

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

Давайте в словарь студентов добавим еще запись Александра c student_id= 1, и, как вы видите, это будет дубль:

student_id

student

grade

1

Александр

11

1

Александр

11

2

Влад

10

3

Сергей 

10

4

Полина

9

5

Ксения

11

6

Алексей

9

Давайте соединим две таблицы с помощью left join и по классике выведем наших студентов и их оценки:

select
   sc.student_id,
   st.student,
   sc.subject,
   sc.score
from
   score_table as sc
left join
   student_table as st on st.student_id = sc.student_id

student_id

subject

score

student

1

SQL

5

Александр

1

SQL

5

Александр

2

Математика

4

Влад

3

Физ-ра

5

Сергей 

4

Математика 

3

Полина

5

SQL

3

Ксения

7

Английский 

2

null

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

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

  1. Перед написанием запроса внимательно изучить таблицы и сопоставить, какие колонки вы будете выводит и где могут быть дубли.
  2. Исключить дубли с помощью DISTINCT в SELECT.
  3. Когда написали запрос, проверьте еще раз дубли через сравнение общего количества значений primary-key и количество уникальных значений. Они должны быть равны.
  4. Вообще понять, а дубли ли это? 
select
   sc.student_id,
   st.student,
   sc.subject,
   sc.score
from
   score_table as sc
left join
   student_table as st distinct on st.student_id = sc.student_id