2016-01-15 2 views
0

Это может быть дубликат, но я не знаю, как правильно искать. Я могу написать базовый sql и узнать концепцию «Декартово произведение». Но я всегда в некоторой степени смущен насчет на в соединении. Пример в SQLServer:sql join 'on' оператор не фильтрует

A | B 
--+-- 
1 | 2 
2 | 3 

select * from ta left join tb on ta.A = 2  --??! 

A | B 
--+-- 
1 | Null 
2 | 2 
2 | 3 

select * from ta left join tb on tb.B = 2 --seems easier to understand 

A | B 
--+-- 
1 | 2 
2 | 2 

Может ли один объяснить 1-й SQL (на ta.A = 2), почему колонка А не фильтруется. Кстати, я знаю самое распространенное использование на ta.ColA = tb.ColB, но в этом вопросе я просто хочу знать, как работает на.

+0

У вас есть ошибка в вашем выходе, что затрудняет понимание проблемы. В вашем первом выводе вторая строка должна иметь 'A = 2', а не' A = 1'. –

+0

Извините, я обновил его. –

ответ

3

LEFT JOIN всегда следуют следующие правила:

  1. Возьмите все строки с левой стороны соединения
  2. Найдите совпадающие строки из правой стороны соединения, используя предложение ON ..., чтобы найти тех, строк.
  3. В зависимости от количества строк, найденных с правой стороны, сделайте следующее:
    • Нет строк: производит один ряд с левой стороны в результатах и ​​сделать все столбцы, которые пришли с правой стороны сторона NULL
    • Один ряд: Смешайте одну строку с левой стороны с одной строки с правой стороны
    • нескольких строк: Смешайте одну строку с левой стороны с каждой из строк с правой стороны, производя множественные строки на выходе

Таким образом, ваш ON TA.A=2 используется только для фильтрации строк с правой стороны.

Теперь у вас есть ошибка в вашем вопросе, которая затрудняет вам просто прочитать, в чем проблема.

Этот выход:

A | B 
--+-- 
1 | Null 
1 | 2    <-- notice A=1 here, this is incorrect 
2 | 3 

должен быть таким:

A | B 
--+-- 
1 | Null 
2 | 2    <-- notice A=2 here 
2 | 3 

В принципе, ваш запрос делает это:

  • Возьмите все строки из TA
  • Найти строки из TB где TA.A=2 это правда, это произойдет только тогда, когда вы находитесь в строке A=2, поэтому у вас есть Null для A=1.
  • Поскольку вы не укажете, какую из нужных строк TB вы хотите, все эти строки будут объединены с одной строкой, где A=2.
+0

Стоит ли разделять «одну строку» и «несколько строк» ​​на отдельные случаи? –

+0

Из опыта, чтобы объяснить это другим, я бы сказал, да. –

3

В LEFT JOIN все строки с левой стороны соединения будут всегда сохранятся. Условие ON определяет, будут ли любые строки с правой стороны успешно соединены с этими строками.

Так,

select * from ta left join tb on ta.A = 2  --??! 

A | B 
--+-- 
1 | Null 
2 | 2 
2 | 3 

Когда A равно 1, условие ta.A = 2 никогда не верно, и так нет строки из tb не сохраняются.

Когда A равно 2, условие ta.A = 2 верно, и так все строки из tb соединены с такими строками в ta.

+0

Примите другое, поскольку он не только ответил, но и исправил мою ошибку в исходном выпуске. Однако вы быстрее! –

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