Как Left Join / IS NULL устраняет записи, которые есть в одной таблице и нет в другой?
Мне трудно понять, почему это происходит.LEFT JOIN / IS NULL исключите записи, которые находятся в одной таблице, а не в другой.
Вот пример
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
WHERE r.value IS NULL
Зачем r.value = NULL уничтожать записи ? Я ничего не понимаю . Я знаю, что упускаю что-то очень основное, но в настоящее время я не могу понять даже это основное. Я был бы признателен, если бы кто-нибудь объяснил мне это подробно .
Мне нужно очень простое объяснение.
11 ответов:
Это можно объяснить следующим образом
mysql> select * from table1 ; +------+------+ | id | val | +------+------+ | 1 | 10 | | 2 | 30 | | 3 | 40 | +------+------+ 3 rows in set (0.00 sec) mysql> select * from table2 ; +------+------+ | id | t1id | +------+------+ | 1 | 1 | | 2 | 2 | +------+------+ 2 rows in set (0.00 sec)Здесь
table1.id <-> table2.t1idТеперь, когда мы делаем
left joinс ключом соединения, и если левая таблица-table1, то она получит все данные из table1 и в несоответствующей записи на table2 будет установлено значение nullmysql> select t1.* , t2.t1id from table1 t1 left join table2 t2 on t2.t1id = t1.id ; +------+------+------+ | id | val | t1id | +------+------+------+ | 1 | 10 | 1 | | 2 | 30 | 2 | | 3 | 40 | NULL | +------+------+------+ 3 rows in set (0.00 sec)Смотрите, что table1.id = 3 не имеет значения в таблице 2, поэтому его значение равно null Когда вы применяете условие where, оно будет выполнять дальнейшую фильтрацию
mysql> select t1.* , t2.t1id from table1 t1 left join table2 t2 on t2.t1id = t1.id where t2.t1id is null; +------+------+------+ | id | val | t1id | +------+------+------+ | 3 | 40 | NULL | +------+------+------+ 1 row in set (0.00 sec)
Предположим, что r-таблица-это сотрудники, а r_table-компьютеры. У некоторых сотрудников нет компьютеров. Некоторые компьютеры еще никому не назначены.
Внутреннее соединение:
SELECT l.*, r.* FROM employees l JOIN computers r ON r.id = l.comp_idДает вам список всех сотрудников, у которых есть компьютер, и информацию о компьютере, назначенном для каждого из них. Сотрудники без компьютера в этом списке не появятся.
Левое соединение:
SELECT l.*, r.* FROM employees l LEFT JOIN computers r ON r.id = l.comp_idДает вам список всех сотрудников. Сотрудники с компьютером покажет информацию о компьютере. Сотрудники без компьютеров будут появляться с нулями вместо информации о компьютере.
Наконец
SELECT l.*, r.* FROM employees l LEFT JOIN computers r ON r.id = l.comp_id WHERE r.id IS NULLЛевое соединение с предложением WHERE будет начинаться с того же списка, что и левое соединение (2), но тогда он будет держать только тех сотрудников, которые не имеют соответствующей информации в компьютерной таблице, то есть сотрудников без компьютеров.
В этом случае выбор чего-либо из таблицы
rбудет просто равен нулю, поэтому вы можно оставить эти поля и выбрать только материал из таблицыl:SELECT l.* FROM ...Попробуйте выполнить эту последовательность выборок и понаблюдайте за выводом. Каждый следующий шаг основывается на предыдущем.
Пожалуйста, дайте мне знать, если это объяснение понятно, или вы хотите, чтобы я уточнил еще немного.ОТРЕДАКТИРОВАНО ДЛЯ ДОБАВЛЕНИЯ: Вот пример кода для создания двух таблиц, используемых выше:
Есть 4 сотрудника. У Бекки и Джона есть компьютеры. У Энн и Боба нет компьютера. (У Энн есть comp_id 7, который не соответствует ни одной строке в таблице computers - значит, у нее на самом деле нет компьютера.)CREATE TABLE employees ( id INT NOT NULL PRIMARY KEY, name VARCHAR(20), comp_id INT); INSERT INTO employees (id, name, comp_id) VALUES (1, 'Becky', 1); INSERT INTO employees (id, name, comp_id) VALUES (2, 'Anne', 7); INSERT INTO employees (id, name, comp_id) VALUES (3, 'John', 3); INSERT INTO employees (id, name) VALUES (4, 'Bob'); CREATE TABLE computers ( id INT NOT NULL PRIMARY KEY, os VARCHAR(20) ); INSERT INTO computers (id, os) VALUES (1,'Windows 7'); INSERT INTO computers (id, os) VALUES (2,'Windows XP'); INSERT INTO computers (id, os) VALUES (3,'Unix'); INSERT INTO computers (id, os) VALUES (4,'Windows 7');
Левая возвращает всю строку из левой таблицы
На r. value = l. value
если для значения l нет значения r, то r пуст
r. значение null будет истинно
В вашем примере результатом будет каждая запись из
t_left, а также каждая соответствующая запись изt_right, где они оба имеют одинаковыйvalue. там, где нет совпадения, вместо значений изt_rightзадаются значенияNULL.where r.value is nullпросто удаляет совпадающие строки, обнаруживая эти значенияnull.По существу говоря ' дайте мне строки из
t_left, которые не соответствуют строкам вt_rightA
right joinвыполняет обратный порядокleft join.
Это основано на разнице между
Но когда вы используетеINNER JOINиLEFT JOIN. При использованииINNER JOINрезультат содержит только строки, соответствующие двум таблицам (на основе условияON).LEFT JOIN, вы также получаете строки в результате для всех строк в первой таблице, которые не имеют совпадения во второй таблице. В этих случаях все результирующие столбцы из второй таблицы заполняютсяNULLв качестве заполнителя.Тест
WHERE r.value IS NULLзатем соответствует этим строкам. Так конечный результат содержит только строки без совпадений.
Left JOIN принимает значения слева и пытается сопоставить таблицу слева по столбцу, указанному на ON если он не находит соответствия, то он интерпретирует столбцы правой таблицы как NULL. следовательно, только те, которые не могут найти совпадение в правой таблице, будут выбраны оператором IS NULL
Во-первых, левое соединение утверждает, что все записи из левой таблицы будут включены, и только те из правой, которые совпадают.
Итак, допустим, у вас есть
red,blueиgreenносок в вашем ящике, а ваш друг толькоred,yellowиblue, левое соединение из вашего ящика к вашим друзьям вернет все носки из вашего ящика (red,blueиgreen) и только совпадающие из ваших друзей (redиblue).Теперь нулевая часть говорит, что вы хотите видеть все носки из вашего ящика, где нет подходящих пар партнеров в ящике ваших друзей, поэтому из всех ваших носков единственный с отсутствующей парой-это носок
green.
Это предложение:
SELECT l.id, l.value FROM t_left l LEFT JOIN t_right r ON r.value = l.valueБудет иметь все элементы из таблицы
t_left, присоединенные ко всем элементам из таблицыt_right. Как вы, вероятно, и сделаете сейчас, вINNER JOINбудут показаны только строки, соответствующие обеим таблицам, так чтоt_leftможет иметь меньше строк , чем все возможные строки. ВLEFT JOIN, у вас есть все строки изt_leftтаблицы плюс соответствующие строки изt_right(если они могут быть объединены). Итак, что происходит со строками в t_left, которые не соответствуют ни одной строке t_right? Все поля из t_right таблица, которая должна была бы содержать данные, будет заполнена нулевыми значениями. Таким образом, если вы выберете только значенияNULLиз правой таблицы, вы найдете все значения из таблицыt_left, которые не совпадают с правой, XD
Это основное различие между внутренним соединением и левым / правым соединением.
Left joinдает все записи из левой таблицы. Если какой-либо ключ, присутствующий в левой таблице, отсутствует в правой таблице, то все столбцы правой таблицы будут иметь значение null, но все значения левой таблицы будут присутствовать.Таким образом, когда вы делаете 'r.value = null`, вы получаете те записи слева, где в правой таблице нет соответствующего ключа.
HTH.
Это просто левый join funda..... следующий запрос получает всю запись из левой таблицы и сопоставленную запись из правой таблицы, если она не совпадает, то возвращает NUll Значение. в конце вы фильтруете данные, используя условие where, которое возвращает значения, которые находятся в левой таблице, но не в правой таблице
SELECT l.id, l.value FROM t_left l LEFT JOIN t_right r ON r.value = l.value WHERE r.value IS NULL
SELECT * FROM a LEFT JOIN b ON a.v = b.v ... WHERE b.id IS NULLЭто супер простая логика:
- Выберите из таблицы " a "
- соедините таблицу "b" (если совпадающие строки существуют-на a. v=b. v в противном случае используйте NULL в качестве значений)
- , где условие: если чего-то не хватает (б.идентификатор имеет значение null) = ОК.
Comments