Головоломка Mysql: условия в ON против ГДЕ

#mysql #sql #join #left-join

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

Вопрос:

Следующие два запроса не возвращают один и тот же результат. Почему ?

Примечание: я нашел этот вопрос как головоломку Mysql, у меня нет больше данных по этому вопросу?

 SELECT table1.*
FROM table1 LEFT JOIN table2
ON table2.table1_id = table1.id 
AND table2.val < 5


SELECT table1.*
FROM table1 LEFT JOIN table2
ON table2.table1_id = table1.id 
WHERE table2.val < 5
  

Ответ №1:

Левое внешнее соединение вернет строки (с нулевыми столбцами из table2, если они были выбраны), когда условие не выполняется, тогда как WHERE отфильтровывает их.

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

1. @MarkByers В проекции не будет никаких нулевых строк (какие столбцы отображать), но запрошенный набор данных будет, и это имеет значение

2. @MarkByers Ну, в запросе № 1 будут нулевые значения из таблицы2.

3. @Adrian, в запросе 2 с помощью a where он превратил запрос во внутреннее соединение в соответствии с ответом Робина ниже. Вот почему набор результатов отличается.

Ответ №2:

Первый запрос вернет все строки из таблицы 1. Соединение по ЛЕВОМУ КРАЮ всегда возвращает все строки из левой таблицы, независимо от того, что вы пишете в условии соединения (однако оно может дублировать строки, если есть несколько совпадений, но поскольку вы объединяетесь по вызываемому полю id , это, скорее всего, уникальный ключ, поэтому дубликатов не будет).

Второй запрос вернет только те строки из таблицы 1, в которых есть соответствующая строка в table2 val < 5 . На самом деле вы могли бы написать INNER JOIN здесь, а LEFT JOIN не потому, что строки, в которых происходит сбой соединения, в любом случае не будут в результирующем наборе из-за WHERE предложения.

Ответ №3:

Первый запрос присоединяется только тогда, когда table2.val < 5 . Вторая фильтрует даже строки table1. Идентичный результат должен быть получен, если вместо этого вы используете INNER JOIN.

Ответ №4:

Пытаясь мыслить как «компилятор«, посмотрите на скобки

 SELECT     table1.*
FROM       table1 
LEFT JOIN  table2 ON (
             table2.table1_id = table1.id 
             AND table2.val < 5
)
  

В этом примере выполняется ЛЕВОЕ ОБЪЕДИНЕНИЕ 2 таблиц, когда условие table2.table1_id = table1.id AND table2.val < 5 истинно.

 SELECT     table1.*
FROM       table1
LEFT JOIN  table2 ON ( table2.table1_id = table1.id )
WHERE      (table2.val < 5)
  

В этом примере выполняется СОЕДИНЕНИЕ по ЛЕВОМУ КРАЮ, когда table2.table1_id = table1.id применяется условие, а затем получаются строки результата table1 LEFT JOIN table2 ON ( table2.table1_id = table1.id ) , в КОТОРЫХ условие table2.val < 5 истинно