Как LEFT OUTER JOIN может вернуть больше записей, чем существует в левой таблице? - PullRequest
135 голосов
/ 27 мая 2009

У меня есть очень простое LEFT OUTER JOIN, чтобы вернуть все результаты из левой таблицы и некоторую дополнительную информацию из гораздо большей таблицы. Левая таблица содержит 4935 записей, но когда я оставляю ее в другой таблице, количество записей значительно увеличивается.

Насколько мне известно, это абсолютное Евангелие, что LEFT OUTER JOIN вернет все записи из левой таблицы с совпадающими записями из правой таблицы и нулевые значения для любых строк, которые не могут быть сопоставлены, поэтому я так понимаю что должно быть невозможно вернуть больше строк, чем существует в левой таблице, но все происходит одинаково!

SQL-запрос следует:

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

Возможно, я допустил ошибку в синтаксисе или мое понимание LEFT OUTER JOIN неполное, надеюсь, кто-то может объяснить, как это могло произойти?

Постскриптум

Спасибо за отличные ответы, мое понимание LEFT OUTER JOINS теперь намного лучше, может ли кто-нибудь предложить способ, которым этот запрос может быть изменен так, чтобы я получал только столько записей, сколько существует в левой таблице?

Этот запрос предназначен исключительно для генерации отчета, а повторяющиеся совпадения просто запутывают вопросы.

/ Postscript

Ответы [ 11 ]

153 голосов
/ 27 мая 2009

LEFT OUTER JOIN вернет все записи из таблицы LEFT, соединенной с таблицей RIGHT, где это возможно.

Если есть совпадения, он все равно будет возвращать все совпадающие строки, поэтому одна строка в LEFT, которая соответствует двум строкам в RIGHT, вернется как две строки, как INNER JOIN.

EDIT: В ответ на ваши изменения я только что еще раз рассмотрел ваш запрос, и похоже, что вы только возвращаете данные из таблицы LEFT. Поэтому, если вам нужны только данные из таблицы LEFT, и вы хотите, чтобы для каждой строки в таблице LEFT возвращалась только одна строка, то вам вообще не нужно выполнять JOIN и вы можете просто выполнить SELECT непосредственно из таблицы LEFT.

94 голосов
/ 27 мая 2009
Table1                Table2
_______               _________
1                      2
2                      2
3                      5
4                      6

SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id

Результаты:

1,null
2,2
2,2
3,null
4,null
28 голосов
/ 27 мая 2009

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

10 голосов
/ 27 мая 2009

В ответ на ваш постскриптум это зависит от того, что вы хотели бы.

Вы получаете (возможно) несколько строк для каждой строки в левой таблице, потому что есть несколько совпадений для условия соединения. Если вы хотите, чтобы ваши итоговые результаты имели то же количество строк, что и в левой части запроса, вам нужно убедиться, что ваши условия объединения вызывают совпадение 1: 1.

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

Если вы смотрите только 1 или 2 столбца из внешнего объединения, вы можете рассмотреть возможность использования скалярного подзапроса, поскольку вам будет гарантирован 1 результат.

8 голосов
/ 27 мая 2009

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

7 голосов
/ 27 мая 2009

LEFT OUTER JOIN, как и INNER JOIN (обычное соединение), вернет столько результатов для каждой строки в левой таблице, сколько совпадений найдет в правой таблице. Следовательно, вы можете получить много результатов - до N x M, где N - количество строк в левой таблице, а M - количество строк в правой таблице.

Это минимальное количество результатов, которое всегда гарантировано в LEFT OUTER JOIN должно быть не менее N.

6 голосов
/ 06 сентября 2014

Обратите внимание, если у вас есть предложение where в таблице "right side" запроса, содержащего левое внешнее соединение ... Если у вас нет записи с правой стороны, удовлетворяющей условию where, то соответствующая запись таблицы 'left side' не появится в результате вашего запроса ....

6 голосов
/ 27 мая 2009

Может ли быть отношение один ко многим между левой и правой таблицами?

4 голосов
/ 27 мая 2009

Если вам нужен только один ряд с правой стороны

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

или просто

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)
1 голос
/ 27 мая 2009

, если несколько (x) строк в Dim_Member связаны с одной строкой в ​​Susp_Visits, в наборе результатов будет x строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...