В чем причина полного внешнего соединения, в результате которого появляется больше строк, чем в любом родительском наборе данных?

Я работаю с двумя наборами данных, которые пытаюсь объединить с помощью команды Join (а ​​не Union).

Я не думаю, что понимаю основы присоединения. Я использовал полное внешнее соединение следующим образом:

    Select
      Table1.col1,
      Table1.col2, 
      Table1.date1,
      Table2.col1,
      Table2.col2,
      Table2.date2
   From Table1 full outer join 
        Table2 On Table1.date1 = Table2.date2

В окончательном комбинированном наборе данных общее количество строк превышает сумму строк в таблицах Table1 и Table2.

Я пытаюсь понять, почему это произошло.

У меня создалось впечатление, что (# строк в CombinedTable) = (# строк в Table1) + (# строк в Table2).

Почему это происходит? Как я могу это исправить?

3 ответа

Решение

Проверь это:

TblJob
Name, Surname, Job
John, White, Developer
John, Black, Tester
John, Grey, Manager

TblDrinksPref
Name, Surname, Drink
John, White, Coffee
John, Black, Tea
John, Grey, Orange Juice

SELECT * FROM tbljob j JOIN tbldrinkspref p ON j.name = p.name

John, White, Developer, John, White, Coffee
John, White, Developer, John, Black, Tea
John, White, Developer, John, Grey, Orange Juice
John, Black, Tester, John, White, Coffee
John, Black, Tester, John, Black, Tea
John, Black, Tester, John, Grey, Orange Juice
John, Grey, Manager, John, White, Coffee
John, Grey, Manager, John, Black, Tea
John, Grey, Manager, John, Grey, Orange Juice

При объединении только первого имени каждая строка в каждой таблице соответствует другой. 3 строки в каждой таблице дают результат 3x3 таблицы; больше суммы строк. Наибольшее количество строк, которые вы получите в результате объединения, - это умножение количества строк, ведущих в объединение. Мы называем это декартовым произведением, и обычно это указывает на наличие ошибки в ваших SQL-соединениях. Это может сделать любое соединение, а не только внешние. Существует соединение (называемое CROSS JOIN), единственная цель которого - произвести на выходе идеальный декартово произведение, потому что иногда мы действительно хотим это сделать, но в большинстве случаев это указывает на проблему.

Что вы можете с этим поделать? Не присоединяйте строки к строкам, которые не связаны друг с другом, сделав условия соединения лучше / точнее:

SELECT * 
FROM tbljob j JOIN tbldrinkspref p 
ON j.name = p.name 
  --the last name is vital to associate rows correctly in this case
  AND j.surname = p.surname

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

Вы получите N примеров и диаграмм, вы должны иметь некоторое представление о соединениях, прежде чем смотреть на эти примеры и диаграммы, я предполагаю, что вы используете MS Sql.

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

если значение из второй таблицы не сопоставлено со значениями столбца первой таблицы, то они возвращаются как null.

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

PS Полное соединение и полное внешнее соединение - это одно и то же!

Рассмотрим две таблицы A с m строками и B с n строками и такой запрос:

select count(*)
from a full join
     b
     on <some condition>;

Эта строка может возвращать (почти) любое число между greatest(n, m) а также n * m.

Он вернется greatest(n, m) если условие всегда было 1 к 1 (например, для идентификаторов).

Он вернется n + m если условие всегда оценивается как ЛОЖЬ.

Он вернется n * m если условие всегда оценивается как ИСТИНА.

Он может возвращать почти любое промежуточное число, за некоторыми исключениями (например, во многих случаях было бы трудно получить n * m- 1 ряды).

Напротив, INNER JOIN может вернуться между 0 а также n * m ряды.

С другой стороны, UNION ALL всегда возвращает в точности сумму строк в двух таблицах, поэтому вы можете запутать UNION ALL а также FULL JOIN.

Другие вопросы по тегам