Подтвердить что ты не робот

В SQL/MySQL какая разница между "ON" и "WHERE" в заявлении о соединении?

Следующие утверждения дают один и тот же результат (один использует on, а другой - с помощью where):

mysql> select * from gifts INNER JOIN sentGifts ON gifts.giftID = sentGifts.giftID;
mysql> select * from gifts INNER JOIN sentGifts WHERE gifts.giftID = sentGifts.giftID;

Я могу видеть только в случае, когда Left Outer Join обнаруживает "непревзойденные" случаи:
(чтобы узнать подарки, которые никогда не посылали никому)

mysql> select name from gifts LEFT OUTER JOIN sentgifts 
           ON gifts.giftID = sentgifts.giftID 
           WHERE sentgifts.giftID IS NULL;

В этом случае сначала используется on, а затем where. Выполняет ли on совпадение, а затем where выполняет "вторичную" фильтрацию? Или существует более общее правило использования on по сравнению с where? Спасибо.

4b9b3361

Ответ 1

WHERE является частью запроса SELECT в целом, ON является частью каждого отдельного соединения.

ON может ссылаться только на поля ранее использованных таблиц.

Если нет фактического совпадения с записью в левой таблице, LEFT JOIN возвращает одну запись из правой таблицы со всеми полями, установленными на NULLS. WHERE затем оценивает и фильтрует это.

В вашем запросе возвращаются только записи из gifts без соответствия в 'sentgifts'.

Здесь пример

gifts

1   Teddy bear
2   Flowers

sentgifts

1   Alice
1   Bob

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID

---

1  Teddy bear   1     Alice
1  Teddy bear   1     Bob
2  Flowers      NULL  NULL    -- no match in sentgifts

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID
WHERE   sg.giftID IS NULL

---

2  Flowers      NULL  NULL    -- no match in sentgifts

Как вы можете видеть, никакое фактическое совпадение не может оставить NULL в sentgifts.id, поэтому возвращаются только те подарки, которые не были отправлены.

Ответ 2

Предложение ON определяет отношения между таблицами.

Предложение WHERE описывает, какие строки вас интересуют.

Много раз вы можете поменять их местами и получить один и тот же результат, однако это не всегда так с левым внешним соединением.

  • Если предложение ON не выполняется, вы все равно получаете строку со столбцами из левой таблицы, но с пустыми значениями в столбцах из правой таблицы.
  • Если WHERE не выполнено, вы вообще не получите эту строку.

Ответ 3

При использовании INNER JOIN, ON и WHERE будет иметь тот же результат. Таким образом,

select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
where t1.Name = 'John'

будет иметь тот же самый результат, что и

select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
    and t1.Name = 'John'

Как вы уже отметили, это не тот случай, когда используется OUTER JOIN. Создание плана запроса зависит от платформы базы данных, а также от особенностей запроса и может быть изменено, поэтому принятие решений только на этой основе не даст гарантированного плана запроса.

Как правило, вы должны использовать столбцы, которые присоединяются к вашим таблицам в разделах и столбцах ON, которые используются для фильтрации в предложениях WHERE. Это обеспечивает наилучшую читаемость.

Ответ 4

Хотя результаты одинаковы, 'ON' сначала выполните соединение, а затем извлекут данные объединенного набора. Поиск быстрее, а загрузка меньше. Но, используя "WHERE", сначала нужно получить два набора результатов, а затем применить условие. Значит, вы знаете, что предпочтительнее.

Ответ 5

  • ON применяется к набору, используемому для создания перестановок каждой записи как части операции JOIN
  • WHERE указывает фильтр, примененный после операции JOIN

По сути, ON заменяет каждое поле, которое не удовлетворяет его условию, значением NULL. Приведенный пример @Quassnoi

gifts

1   Teddy bear
2   Flowers

sentgifts

1   Alice
1   Bob

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID

---

Перестановки LEFT JOIN были бы рассчитаны для следующих коллекций, если бы не было условия ON:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {'ALICE', 'Bob'} }

с g.giftID = sg.giftID ON, это коллекции, которые будут использоваться для создания перестановок:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL, NULL} }

который в действительности является:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} }

и так приводит к левому соединению:

Teddy bear Alice
Teddy bear Bob
Flowers    NULL

и для ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ у вас будет:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} } для LEFT JOIN и { 'ALICE': {'Teddy bear', NULL}, 'Flowers': {'Teddy bear', NULL} } для RIGHT JOIN:

Teddy bear Alice
Teddy bear Bob
Flowers    NULL

Если бы у вас также было такое условие, как ON g.giftID = 1 это было бы

{ NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }

который для LEFT JOIN приведет к

Flowers NULL

и для FULL OUTER JOIN будет получено { NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} } для LEFT JOIN и { 'ALICE': {NULL, NULL}, 'Flowers': {NULL, NULL} } для RIGHT JOIN

NULL    Alice
NULL    Bob
Flowers NULL

Примечание. В MySQL нет FULL OUTER JOIN, и вам необходимо применить UNION к LEFT JOIN и RIGHT JOIN.

Ответ 6

Если вы используете JOIN, вам нужно указать условия, в которых вы присоединяетесь. Этот список находится в предложении ON. Предложение WHERE используется для условий для данных в любом месте запроса.