2013-11-12 5 views
1

У меня возникли проблемы с этим.Запрос с левым наружным соединением

Согласно Jeff Atwood A Visual Explanation of SQL Joins Левое внешнее соединение дает полный набор записей из таблицы A с соответствующими записями (если таковые имеются) в таблице B. Если совпадения нет, правая часть будет содержать нуль.

В левой таблице (TableA) нет дубликатов. В правом столеB имеется 1 или 2 записи для каждого номера клиента. PrimaryTP обозначает один как первичный с 1, а другой имеет 0.

Мне не нужно включать строку And B.PrimaryTP = 1, потому что TableA не имеет дубликатов. Но если я оставлю это, я получаю дубликаты клиентских номеров. Зачем?

Можете ли вы помочь мне понять, как это работает. Это очень смущает меня. Логика And B.PrimaryTP = 1 ускользает от меня. Но, похоже, это работает. Тем не менее, я боюсь доверять этому, если я этого не понимаю. Можете ли вы помочь мне понять это. Или у меня есть логическая ошибка, скрытая в запросе?

SELECT A.ClientNum --returns a list with no duplicate client numbers 
FROM (...<TableA> 
) as A 

Left Outer Join 

<TableB> as B 
on A.ClientNum = B.ClientNum 

--eliminate mismatch of (ClientNum <> FolderNum) 
Where A.ClientNum Not In 
(
    Select ClientNum From <TableB> 
    Where ClientNum Is Not Null 
    And ClientNum <> IsNull(FolderNum, '') 
) 

--eliminate case where B.PrimaryTP <> 1 
And B.PrimaryTP = 1 
+0

Wow! Спасибо за помощь. Теперь имеет смысл, как многократные записи по праву вызывают дубликаты. Благодарю. –

ответ

1

Разница между INNER JOIN и LEFT JOIN является только то, что LEFT JOIN по-прежнему возвращает строки в таблице А, когда нет соответствующих строк в таблице B.

Но это все еще JOIN, что означает, что если в таблице B имеется более одной соответствующей строки, она будет присоединяться к строке из таблицы А к каждой из них.

Так что если вы хотите, чтобы вы получили не более одного результата для каждой строки в таблице A, вы должны убедиться, что не найдено ни одной строки из таблицы B - следовательно, And B.PrimaryTP = 1.

0

LEFT OUTER JOIN даст вам все записи из A с всех совпадающих записями из B. Разница с INNER JOIN заключается в том, что если есть нет совпадающих записей в B, то объединение INNER будет полностью опускать запись от A, тогда как объединение LEFT будет содержать строку с результатами от A.

В вашем случае, однако, вы также можете проверить ключевое слово DISTINCT.

1

Если у вас есть один номер клиента в A и два совпадения в таблице B, вы получите дубликаты.

Предположим, у вас есть следующие данные,

Table-A(client Num) Table-B(client Num) 
1   2 
2   2 

The left Join Results 

Table-A(client Num) Table-B(client Num) 
1      (null) 
2      2 
2      2 

Это является причиной дублей. Поэтому вам нужно взять различные значения из таблицы B или выполнить Distinct в наборе результатов.

1

Мне не нужно включать строку И B.PrimaryTP = 1, потому что TableA не имеет дубликатов. Но если я оставлю это, я получаю дубликаты клиентских номеров. Зачем?

Поскольку обе строки в правой таблице соответствуют строке в левой таблице. SQL Server не может выводить треугольный результат; он должен показывать столбцы из обеих таблиц для каждой объединенной строки. И это справедливо и для INNER JOIN.

DECLARE @a TABLE(a INT); 
DECLARE @b TABLE(b INT); 

INSERT @a VALUES(1),(2); 
INSERT @b VALUES(1),(1); 

SELECT a.a, b.b FROM @a AS a 
LEFT OUTER JOIN @b AS b ON a.a = b.b; 

SELECT a.a, b.b FROM @a AS a 
INNER JOIN @b AS b ON a.a = b.b; 

Результаты:

a b 
-- ---- 
1 1 
1 1 
2 NULL 

a b 
-- -- 
1 1 
1 1 
1

по ссылке, которую вы дали стыки поясняются очень хорошо. Таким образом, проблема в том, что у вас есть несколько записей из таблицы A (независимо от того, что нет дубликатов) заключается в том, что для 1 записи в A в B есть 2 записи (в некоторых случаях). Чтобы этого избежать, вы можете использовать либо предложение DISTINCT, либо предложение GROUP BY.

Смежные вопросы