MySQL SELECT Tree Parent IDs

Как я могу сортировать записи инструкции SELECT, чтобы они представляли действительное дерево?

Все мои попытки показывают под-узлы, вложенные под неправильные родительские узлы. Какой самый надежный способ добиться этого заказа?

Данные

ID Parent ID Title -------------------------------------------- 0 NULL Root 1 0 Node A 2 0 Node B 3 1 Sub-Node C 4 1 Sub-Node D 5 3 Sub-Node E 

Вывод

 ID Parent ID Title -------------------------------------------- 0 NULL Root 1 0 Node A 3 1 Sub-Node C 5 3 Sub-Node E 4 1 Sub-Node D 2 0 Node B 

Визуализация данных

 Root Node A Sub-Node C Sub-Node E Sub-Node D Node B 

Solutions Collecting From Web of "MySQL SELECT Tree Parent IDs"

Вы можете использовать вложенные наборы. Ознакомьтесь с этой статьей:

Управление иерархическими данными в MySQL

Автор описывает несколько разных методов построения иерархии в SQL, в комплекте с примерами запросов. Это очень хорошо читать об этом предмете!

Следуя совету @Blindy, я реализовал этот вид с PHP. Вот две функции, которые, похоже, довольно легко решают эту проблему.

 protected function _sort_helper(&$input, &$output, $parent_id) { foreach ($input as $key => $item) if ($item->parent_id == $parent_id) { $output[] = $item; unset($input[$key]); // Sort nested!! $this->_sort_helper(&$input, &$output, $item->id); } } protected function sort_items_into_tree($items) { $tree = array(); $this->_sort_helper(&$items, &$tree, null); return $tree; } с protected function _sort_helper(&$input, &$output, $parent_id) { foreach ($input as $key => $item) if ($item->parent_id == $parent_id) { $output[] = $item; unset($input[$key]); // Sort nested!! $this->_sort_helper(&$input, &$output, $item->id); } } protected function sort_items_into_tree($items) { $tree = array(); $this->_sort_helper(&$items, &$tree, null); return $tree; } 

Мне было бы интересно услышать, есть ли более простой подход, но, похоже, это работает.

MySQL не поддерживает рекурсивные запросы

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

См. Эти сообщения для некоторых идей и примеров:

Иерархия категорий (PHP / MySQL)

как мы можем написать mysql-запрос, где у родительского идентификатора есть дочерний идентификатор, а в следующий раз дочерний id – родительский идентификатор, как я могу это сделать?

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

 function orderChildren($data){ $tree = array(); foreach($data as $value){ if($value['parent_id'] == null){ // Values without parents $tree[$value['id']] = $this->goodParenting($value, $data); } } return $tree; } private function goodParenting($parent, $childPool){ foreach($childPool as $child){ if($parent['id'] == $child['parent_id']){ $parent['children'][$child['id']] = $this->goodParenting($child, $childPool); } } return $parent; } 

Вот еще один способ сделать вашу функцию PHP.

 function buildTree() { $data = array(); $pointers = array(); $sql = "SELECT ID,PARENT,TITLE FROM TREE ORDER BY TITLE ASC"; $res = $this->db->query($sql); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { if(!isset($pointers[$row['ID']])) { $pointers[$row['ID']] = $row; } if(!empty($row['PARENT'])) { if(!isset($pointers[$row['PARENT']])) { $pointers[$row['PARENT']] = $row; } $pointers[$row['PARENT']][$row['ID']] = &$pointers[$row['ID']]; } else { $data[$row['ID']] = &$pointers[$row['ID']]; // This is our top level } } unset($pointers); return $data; } этот function buildTree() { $data = array(); $pointers = array(); $sql = "SELECT ID,PARENT,TITLE FROM TREE ORDER BY TITLE ASC"; $res = $this->db->query($sql); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { if(!isset($pointers[$row['ID']])) { $pointers[$row['ID']] = $row; } if(!empty($row['PARENT'])) { if(!isset($pointers[$row['PARENT']])) { $pointers[$row['PARENT']] = $row; } $pointers[$row['PARENT']][$row['ID']] = &$pointers[$row['ID']]; } else { $data[$row['ID']] = &$pointers[$row['ID']]; // This is our top level } } unset($pointers); return $data; } не function buildTree() { $data = array(); $pointers = array(); $sql = "SELECT ID,PARENT,TITLE FROM TREE ORDER BY TITLE ASC"; $res = $this->db->query($sql); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { if(!isset($pointers[$row['ID']])) { $pointers[$row['ID']] = $row; } if(!empty($row['PARENT'])) { if(!isset($pointers[$row['PARENT']])) { $pointers[$row['PARENT']] = $row; } $pointers[$row['PARENT']][$row['ID']] = &$pointers[$row['ID']]; } else { $data[$row['ID']] = &$pointers[$row['ID']]; // This is our top level } } unset($pointers); return $data; }