Выборка из MySQL с рекурсией, решение на PHP
Как известно рекурсивные запросы MySQL не поддерживает, что порождает множество сложностей при необходимости получить данные, например в древовидной структуре. Но есть ряд изящных решений на PHP, которые можно использовать, для построения древовидных массивов из полученных данных от БД.
Сразу оговорюсь. Распространенный метод, которым пользуются многие новички, не самый лучший и даже более того, он может положить весь веб-сервер на лопатки, или выбить из процессов MySQL. Как минимум это чревато сильными притормаживании при работе такого метода. Что это я, все вокруг да около, собственно вот он сам метод:
(в примере используется класс для работы с БД и его методы: getAll — выборка списка строк из БД)
$sql="SELECT * FROM table WHERE parent_id = 0 ORDER BY id ASC"; // получаем список элементов лежащих в корне $items = $DB->getAll($sql); // получаем список записей из БД $new_array = array(); // Новый массив, содержащий дерево foreach($items as $item) { $sql="SELECT * FROM table WHERE parent_id = '{$item['id']}' ORDER BY id ASC"; // получаем список элементов потомков $items_2 = $DB->getAll($sql); // получаем список записей из БД $item['child'] = $items_2; $new_array[]=$item; } |
Многочисленные запросы в БД для выборки потомков и построения дерева. Вариант, но крайне нагружающий MySQl. Так, что я предостерегаю вас от его использования.
По этому, следует использовать немного модифицированный алгоритм, где выборка будет происходить единожды, и выбираться будет сразу вся таблица из БД, а уже далее средствами PHP производиться раскладка выборки в многомерный древовидный массив. Пример:
$sql="SELECT * FROM table ORDER BY id ASC"; // получаем список элементов лежащих в корне $rs= $DB->getAll($sql); // получаем список записей из БД $rs2 = array(); foreach ($rs as $row) { $rs2[$row['parent_id']][] = $row; } function RecursiveTree2(&$rs,$parent) { $out = array(); if (!isset($rs[$parent])) { return $out; } foreach ($rs[$parent] as $row) { $chidls = RecursiveTree2($rs, $row['id']); if ($chidls) $row['childs'] = $chidls; $out[] = $row; } return $out; } print_r(RecursiveTree2($rs2 ,0)); |
Несколько массивов, которые используются как временные, но зато всего один запрос к базе данных. Автор данного решение, для наглядности сгруппировал выборку в двумерный массив, при этом осуществил группировку по родителю.
Следующий пример, вообще решает задачу в рамках одного цикла. При этом используется вспомогательный массив, которых хранит значение, а именно «путь» к родительскому элементу ветки, с целью дописать к нему новую ветку(потомка).
Пример: $x[1][‘childs’][1][‘childs’][0], таким образом мы знаем куда дописать потомка и тем самым построить дерево.
$sql="SELECT * FROM table ORDER BY id ASC"; // получаем список элементов лежащих в корне $rs= $DB->getAll($sql); // получаем список записей из БД $tree = array(0=>array('id'=>0, 'parent_id'=>0, 'value'=>'root')); $temp = array(0=>&$tree[0]); foreach ($rs as $val) { $parent = &$temp[ $val['parent_id'] ]; if (!isset($parent['childs'])) { $parent['childs'] = array(); } $parent['childs'][$val['id']] = $val; $temp[$val['id']] = &$parent['childs'][$val['id']]; } unset($rs, $temp, $val, $parent); print_r($tree[0]['childs']); |
На закуску еще один пример вывода дерева, например такой пример может применяться при выводе категорий с вложенным неограниченным числом подкатегорий
SELECT ID, ParentID, Title FROM Tree; <?php while($row = mysql_fetch_assoc($res)) { $tree[$row[ParentID]][$row[ID]] = $row[Title];} function ShowTree($tree, $pid=0) { echo ; foreach( $tree as $id => $root) { if($pid!=$id)continue; if(count($root)) { foreach($root as $key => $title) { echo {$title}; if(count($tree[$key]))ShowTree($tree,$key); } } } echo ; } |
Надеюсь данный пост будет вам полезен. Пост написан в рамках заметки, для самого себя и конечно читателей моего блога. Примеры позаимствованы из блога Абрамова Тимура.
Похожие записи
Оставить комментарий
- Перенести ли домены с Рег.ру на Бегет? спросил (а) Виктор
- RuCaptcha bot и бан по IP спросил (а) Родмик
- MySQL запрос с несколькими JOIN спросил (а) Александр
- MySQL выбрать данные из двух таблиц спросил (а) Виталий
- Редирект при переносе сайта на WordPress спросил (а) Николай
Archive
- +2019 (2)
- Февраль 2019 (2)
- +2018 (44)
- Декабрь 2018 (4)
- Ноябрь 2018 (7)
- Октябрь 2018 (8)
- Сентябрь 2018 (1)
- Август 2018 (4)
- Июль 2018 (5)
- Май 2018 (3)
- Апрель 2018 (7)
- Март 2018 (1)
- Февраль 2018 (2)
- Январь 2018 (2)
- +2017 (19)
- Декабрь 2017 (2)
- Ноябрь 2017 (1)
- Октябрь 2017 (1)
- Сентябрь 2017 (2)
- Июль 2017 (1)
- Июнь 2017 (1)
- Май 2017 (2)
- Апрель 2017 (3)
- Март 2017 (2)
- Февраль 2017 (1)
- Январь 2017 (3)
- +2016 (37)
- Декабрь 2016 (3)
- Ноябрь 2016 (3)
- Октябрь 2016 (2)
- Сентябрь 2016 (3)
- Август 2016 (7)
- Июнь 2016 (3)
- Май 2016 (3)
- Апрель 2016 (3)
- Март 2016 (1)
- Февраль 2016 (1)
- Январь 2016 (8)
- +2015 (36)
- Ноябрь 2015 (5)
- Октябрь 2015 (4)
- Сентябрь 2015 (1)
- Август 2015 (8)
- Июнь 2015 (1)
- Май 2015 (4)
- Апрель 2015 (8)
- Март 2015 (3)
- Февраль 2015 (2)
- +2014 (26)
- Ноябрь 2014 (2)
- Октябрь 2014 (5)
- Сентябрь 2014 (6)
- Июль 2014 (1)
- Июнь 2014 (2)
- Май 2014 (3)
- Апрель 2014 (6)
- Февраль 2014 (1)
- +2013 (27)
- Декабрь 2013 (2)
- Ноябрь 2013 (1)
- Октябрь 2013 (1)
- Август 2013 (1)
- Июль 2013 (3)
- Июнь 2013 (10)
- Май 2013 (1)
- Апрель 2013 (2)
- Февраль 2013 (3)
- Январь 2013 (3)
- +2012 (42)
- Декабрь 2012 (2)
- Ноябрь 2012 (3)
- Октябрь 2012 (7)
- Сентябрь 2012 (2)
- Август 2012 (1)
- Июль 2012 (3)
- Июнь 2012 (2)
- Май 2012 (6)
- Апрель 2012 (2)
- Март 2012 (8)
- Февраль 2012 (5)
- Январь 2012 (1)
- +2011 (57)
- Декабрь 2011 (6)
- Ноябрь 2011 (2)
- Октябрь 2011 (3)
- Сентябрь 2011 (5)
- Август 2011 (4)
- Июль 2011 (3)
- Июнь 2011 (3)
- Май 2011 (3)
- Апрель 2011 (4)
- Март 2011 (10)
- Февраль 2011 (5)
- Январь 2011 (9)
- +2010 (43)
- Декабрь 2010 (7)
- Ноябрь 2010 (21)
- Октябрь 2010 (14)
- Сентябрь 2010 (1)
Свежие записи
- Свой PHP фреймворк для своих проектов и не только 15.02.2019
- Интеграция с API страховой компании АльфаСтрахование 12.02.2019
- Таблица соотношений дохода и риска при инвестициях в покупку сайта 31.12.2018
- Перенос бизнес процессов из головы на Web-платформу 21.12.2018
- Интеграция на сайт кнопки Купить в кредит от Тинькофф 17.12.2018

