2016-04-21 3 views
0

В базе данных есть таблица называется категория:Понимание этого SQL LEFT JOIN (с IS NULL), например

CREATE TABLE category(
     category_id INT AUTO_INCREMENT PRIMARY KEY, 
     name VARCHAR(20) NOT NULL, 
     parent INT DEFAULT NULL 
); 

Он был создан, чтобы сделать смежный список Model Tree. Вот то, что находится внутри таблицы в настоящее время:

enter image description here

В этом примере (вы можете найти ссылку источника на дне), был использован следующий SQL-код для получения элементов «листа» в таблице , при этом элементы «leaf» являются строками в таблице, в которых не было другой строки, использующей свой «category_id» в столбце «parent». Следующий код был запущен:

SELECT t1.name FROM 
category AS t1 LEFT JOIN category as t2 
ON t1.category_id = t2.parent 
WHERE t2.category_id IS NULL; 

результат предыдущего кода SQL дает этот результат:

enter image description here

Например, не существует ни одна строка в таблице, которая имеет значение 3 внутри родительский столбец, поэтому TUBE (с category_id == 3) является элементом «leaf».

ВОПРОС: Почему этот код sql логически дал этот результат? Я рад, что это так, потому что это то, что мне было нужно, но я не могу окутать голову вокруг рассуждений.


источник например: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

+1

«Внешние соединения» с проверками «null» - это общий шаблон, чтобы увидеть, существует ли запись в таблице, в этом случае проверяя, является ли 'category_id'' parent'. Очень похоже на использование 'not exist' или' not in'. – sgeddes

ответ

2

Всякий раз, когда вы видите этот шаблон:

SELECT ... 
FROM  TableA 
LEFT JOIN TableB ON TableA.column = TableB.column 
WHERE  TableB.id is null 

Думают:. «Найти строки в TableA, которые не существуют в TableB`

Ваш запрос означает «найти категории, у которых нет дочернего элемента». Легче понять, если вы удалите предложение WHERE и добавьте еще несколько столбцов в запрос:

SELECT  t1.category_id, 
      t1.name, 
      t2.name AS ChildName 
FROM  category AS t1 
LEFT JOIN category as t2 ON t1.category_id = t2.parent 

Вот что происходит в вашем запросе:

  1. Начните с category столом, он же оценивает это как t1 и t2. С этого момента я буду ссылаться на псевдонимы.
  2. Для каждой строки в t1, найти все записи в t2, которые идентифицируют, что t1 строки в качестве родителя
  3. Если t1 строка не имеет ребенка, t2.category_id будет нулевым
  4. Мы хотим, чтобы фильтровать только для t1 строк, которые имеют нет ребенка
+0

Хорошо, поэтому я очень близко понимаю! line 1 perfect, строка 2 совершенна, строка 3 ** Если строка t1 не имеет дочернего элемента, t2.category_id будет null **, где я запутался. Не все ли ячейки в столбце t2.category_id имеют значения с самого начала? – Webeng

+0

Подумайте «если я не могу найти для вас ребенка, я оставлю« null »вместо вашего« category_id »вашего ребенка –

+0

. Правильно ли это было бы? ?:« FROM категория AS t1 LEFT JOIN category as t2 ON t1.category_id = t2.parent' сначала перечисляет всю информацию t1 и добавляет только информацию о столбцах MATCHING t2. Поскольку некоторые t1.category_id не соответствуют ни одному t2.parent, они будут иметь значения NULL как для t2.parent AND t2.category_id. Оттуда код говорит: 'WHERE t2.category_id IS NULL' (мне нужны только те, которые не совпадают), и нужен только столбец имен' SELECT t1.name'? Это также означает, что я мог бы заменить «WHERE t2.category_id IS NULL;» с «WHERE t2.parent_id IS NULL;» и получить тот же результат? – Webeng

0

Я думаю, было бы легче увидеть, что происходит, если вы переименовать таблицу псевдоним:

SELECT tparent.name 
     FROM category AS tparent 
     LEFT JOIN category as tchild 
     ON tparent.category_id = tchild.parent 
    WHERE tchild.category_id IS NULL; 

Теперь вам будет проще узнать, что вы просите, это список всех имен родительских категорий, у которых нет детей [tchild.category_id IS NULL]

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