Как LEFT OUTER JOIN может вернуть больше записей, чем существует в левой таблице?


165

У меня есть очень простой 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


5
Чтобы «вернуть столько записей, сколько существует в левой таблице», вам нужно указать, какую строку с правой стороны выбрать, если будет несколько совпадений.
АК

1
как вы это укажете? Я хотел бы вернуть первый матч.
Саймон Кросс

1
Вы должны определить, что подразумевается под первым совпадением. Вы хотите самую раннюю запись, ту, которая имеет самый высокий идентификатор или что?
HLGEM

1
Если вы соответствуете первичному ключу в дополнительной таблице, ваше утверждение верно.
Prageeth Godage

Я часто использую ресурс , как это в качестве шпаргалки при создании запросов. Если ссылка когда-либо умирает, просто Google SQL присоединиться ; это диаграммы Венна различных типов соединений.
Зимано

Ответы:


190

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

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

РЕДАКТИРОВАТЬ: В ответ на ваши изменения, я только что еще раз рассмотрел ваш запрос, и похоже, что вы только возвращаете данные из таблицы LEFT. Поэтому, если вам нужны только данные из таблицы LEFT, и вы хотите, чтобы для каждой строки в таблице LEFT возвращалась только одна строка, тогда вам вообще не нужно выполнять JOIN и вы можете просто выполнить SELECT непосредственно из таблицы LEFT.


1
Причиной присоединения к правой таблице было то, что я получил записи только слева, где в правой таблице была хотя бы одна запись, но большое спасибо за объяснение.
Джей Уайльд

125
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

1
Такой простой, и в то же время такой мощный.
kiradotee

39

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


12

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

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

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

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


4
Это хороший ответ, поскольку он предлагал, как вернуть только строки из левой таблицы.
Карнс

9

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


8

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

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


1
Я начал думать, когда число строк равно N x M, и единственная реальная ситуация, которая приходит мне в голову, это когда N или M равно 1. Вы согласны?
BartoszMiller

2
Нет не знаю Вы не должны думать об условии соединения как о соединении равенства ключей. Это может быть произвольное условие, например, диапазоны дат, неравенства и т. Д. Два крайних случая: (a) N строк не имеют ни одного совпадения среди M строк, тогда левое внешнее объединение приводит к N строкам, сопоставленным с NULL. (b) каждая из N строк соответствует всем M строкам, тогда результатом является N x M строк.
topchef 26.09.13

1
Вы правы, я думал об объединениях только с точки зрения равенства ключей. Мне нравится ваш пример из "дела б". Я считаю, что «каждая из N строк соответствует всем M строкам» - это общий рецепт, когда возвращается N x M строк, что довольно сложно представить, если думать только о равенстве ключей.
BartoszMiller


6

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


1
Затем вы должны добавить условие в предложение ON соответствующего LEFT OUTER JOIN.
Мик

6

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

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
Поскольку вы не предоставили DDL и DML, я не проверял. Во всяком случае, я думаю, что существует, что вы хотите. Попробуйте это: ВЫБЕРИТЕ SuspReason, SiteID FROM (ВЫБЕРИТЕ SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER () OVER (PARTITION by SUSP.Susp_Visits.SiteID ORDER SUSP.Susp_SISSISSISSISSISSISSISSISSIS ПРИСОЕДИНЯЙТЕСЬ К DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum) КАК ГДЕ rn = 1
АК

2

Кажется, что в таблице DATA.Dim_Member есть несколько строк на строку SUSP.Susp_Visits.


2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.