Путаница во внутреннем соединении и внешнем соединении

#sql #join

#sql #Присоединиться

Вопрос:

Я пытаюсь получить данные из одной таблицы, поэтому я присоединяюсь к ней следующим образом:

 SELECT A.ACCT_NO
FROM   ACCOUNT AS A
RIGHT OUTER JOIN CUSTOMER AS C
       ON A.CUST_ID = C.CUST_ID
WHERE  C.FIRST_NM = 'ADAM';
  

Проблема сейчас в том, что я несколько смущен тем, как функционируют соединения. Если я изменю его на:

 LEFT OUTER JOIN CUSTOMER AS C
  

Или даже:

 INNER JOIN CUSTOMER AS C
  

Я получаю те же точные данные! Я следую этой диаграмме прямо здесь:

http://i.stack.imgur.com/1UKp7.png

Исходя из этого, я предположил, что будет работать только ПРАВИЛЬНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ, потому что оно только извлекает столбцы из CUSTOMER. Однако, похоже, это не так, поскольку работают оба внешних соединения. Кроме того, я был потрясен, увидев, что внутреннее соединение также работает. Почему это? Или это потому, что мне не хватает ключевых понятий в отношении join в SQL?

Спасибо!

Комментарии:

1. Вы, похоже, были очень смущены тем, как работают объединения. en.wikipedia.org/wiki/Join_ (SQL)

2. При использовании внешних соединений в объединении ДОЛЖНЫ быть указаны ограничивающие критерии для таблицы, в которой вам нужны только совпадающие записи, или вы должны использовать условие или для обработки NULL

3. Вы сказали: «Или это потому, что я упускаю ключевые понятия, касающиеся join в SQL? » Да, этот момент. Вам не хватает ключевой концепции, касающейся того, когда к результирующему набору применяются ограничивающие критерии, по сравнению с тем, когда генерируется декартова форма объединения.

Ответ №1:

Этот запрос вернет значения null для значений, которых нет в таблице Account, и всех записей из таблицы Customer

 SELECT *
FROM   ACCOUNT AS A
RIGHT OUTER JOIN CUSTOMER AS C
       ON A.CUST_ID = C.CUST_ID
  

Этот запрос вернет значения null для значений, которых нет в таблице Customer, и всех записей из таблицы Account

 SELECT *
FROM   ACCOUNT AS A
LEFT JOIN CUSTOMER AS C
       ON A.CUST_ID = C.CUST_ID
  

Этот запрос не вернет строки, которые не имеют эквивалентов в таблице customer, поэтому только строки из учетных записей, у которых есть клиенты.

 SELECT *
FROM   ACCOUNT AS A
INNER JOIN CUSTOMER AS C
       ON A.CUST_ID = C.CUST_ID
  

Комментарии:

1. и WHERE C.FIRST_NM = 'ADAM' превращает LEFT JOIN CUSTOMER AS C во внутреннее соединение

Ответ №2:

При использовании внешних соединений в соединении ДОЛЖНЫ быть размещены ограничивающие критерии для таблицы, в которой вам нужны только совпадающие записи, или вы должны использовать условие или для обработки NULL. Если вы этого не сделаете, вы получите те же результаты, что и при ВНУТРЕННЕМ соединении. Это связано с тем, когда происходит объединение, и с тем, когда применяются критерии предложения where. Когда ограничивающий критерий находится в соединении, это происходит перед соединением, в предложении where, после. Когда в предложении where значения NULL, сгенерированные внешним соединением, затем исключаются … предложением where … что делает его похожим на внутреннее соединение.

Поскольку я думаю, что вам нужны все учетные записи, но только информация о клиенте, где имя — Адам, вам нужно левое соединение, но переместите критерии предложения where в соединение.

ПРЕДПОЧТИТЕЛЬНЫЙ:

 SELECT A.ACCT_NO
FROM   ACCOUNT AS A
LEFT OUTER JOIN CUSTOMER AS C
       ON A.CUST_ID = C.CUST_ID
       AND C.FIRST_NM = 'ADAM';
  

или

Если вы должны

     SELECT A.ACCT_NO
    FROM   ACCOUNT AS A
    LEFT OUTER JOIN CUSTOMER AS C
           ON A.CUST_ID = C.CUST_ID
  WHERE (C.FIRST_NM = 'ADAM' OR c.First_NM is null)
  

но c.First_NM не должен иметь значения null, иначе вы не сможете отличить значение null в соединении от значения null в записи.

http://blog.codinghorror.com/a-visual-explanation-of-sql-joins / за помощью по объединениям.

ПОРЯДОК таблиц имеет значение…

  • Если вам нужны все клиенты и только те учетные записи, которые соответствуют клиенту, тогда используйте RIGHT JOIN , как вы указали.
  • Если вам нужны все учетные записи и только те клиенты, у которых есть связанная учетная запись, используйте LEFT JOIN
  • Если вы хотите, чтобы все учетные записи и все клиенты использовали FULL OUTER JOIN
  • Если вам нужны только клиенты с учетными записями, используйте INNER JOIN

Ответ №3:

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

Если нет несоответствий ключей, все RIGHT JOIN , LEFT JOIN и INNER JOIN должны возвращать одни и те же данные.

Итак, вы видите, что для каждого клиента, названного 'ADAM' в CUSTOMER , есть соответствующая запись в ACCOUNT .