Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вывод дерева из БД 
:(
    Опции темы
mark2011
Дата 28.7.2011, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 28.6.2011

Репутация: 2
Всего: 2



Избитая, конечно, тема, ну да ладно....

В прикреплённом файлике структура таблицы. Задача проста - вывести её на экран. 

Делаю так:

Код

global $db;    

//получить корень
//первый вызов функции: $this->PrintTree(0);
$db->query('SELECT cat_id, cat_name FROM photo_browser_categories WHERE parent_id = ' . $parent_id);
$r = $db->parse_query('array');
$var.= $r['cat_name']."<br>";


Так, занесли в переменную корень дерева... Хорошо, идём дальше...

Код

//выбрать тот элемент, у которого parent_id = cat_id текущего элемента
$db->query('SELECT cat_id, cat_name FROM photo_browser_categories WHERE parent_id = "' . $r['cat_id'] .'"');
$rr = $db->parse_query('array');
$var .= $rr['cat_name']."<Br>";


Логично, правда? Посмотрите на рисунок: у корня cat_id=29, он же parent_id у второго элемента. Казалось бы, повторяй эту конструкцию в цикле, ан нет...

У элемента "1.1.1"  cat_id=31, но не существует элемента, у которого parent_id=31.  Значит автоматически указанное выше условие рекурсии недействительно.

Из этого совершенно непонятно условие выхода из рекурсии... если честно, я даже его словами не могу сформулировать...  

Знаю, что существуют обходы деревьев (префиксный, постфиксный и инфиксный) но, насколько я знаю, это для деревьев Nested Sets, там где используется left_id, right_id... А у меня очень простая структура. 

В общем то надо условие повтора (ради чего рекурсия) и условие выхода из рекурсии...

Всем откликнувшимся огромное спасибо smile

Присоединённый файл ( Кол-во скачиваний: 34 )
Присоединённый файл  dbtree.jpg 23,88 Kb
PM WWW ICQ Skype   Вверх
Sanchezzz
Дата 31.7.2011, 03:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



что то типо того должно быть я так понимаю ?

Код

function Tree($id=0, $level=0, $i=0) {
$s = "SELECT cat_id, cat_name FROM photo_browser_categories WHERE parent_id = '{$id}";
$res = mysql_query($s);
if( mysql_num_rows($res) > 0){
        $level++;    
        while($r = mysql_fetch_assoc($res){
            $i++;
            print_R($r);
            Tree($r['cat_id']);
            
        }
    }else{
        $level--;
    }
}

tree(0);


parent_id должен быть в таблицы по дефолту стоять 0 по умолчанию если он не является потомком.


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
mark2011
Дата 2.8.2011, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 28.6.2011

Репутация: 2
Всего: 2



Sanchezzz
Такой вариант не работает однозначно, я проверил.

Но вот о чём я задумался.... в принципе дерево можно всё за один проход передать в массив и дальше уже работать с этим массивом. С другой стороны, дерево может быть очень большое и массив может получиться огромный. Вот.... возникает вопрос, где будет больше накладных расходов - при прохождении массивом, или прямым рекурсивным выводом из базы?
PM WWW ICQ Skype   Вверх
baldina
Дата 2.8.2011, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(mark2011 @  2.8.2011,  09:33 Найти цитируемый пост)
в принципе дерево можно всё за один проход передать в массив и дальше уже работать с этим массивом

нет никакой разницы откуда получать данные, из базы или массива
Цитата(mark2011 @  28.7.2011,  16:52 Найти цитируемый пост)
У элемента "1.1.1"  cat_id=31, но не существует элемента, у которого parent_id=31

на приведенном рисунке существует... но допустим что нет. это означает, что этот элемент - лист. конец рекурсии.
вот если бы наоборот, parent_id != 0, но элемента с таким cat_id нет. это означает, что целостность данных нарушена. возможно, такая ситуация вполне штатная, просто при обновлениях базы забыли про это поле. тогда просто следует принять решение (с точки зрения задачи), что означают такие записи. очевидных варианта два: либо считать данный элемент корнем еще одного дерева (parent_id=0) либо просто не рассматривать его.
вообще, если мы идем от корня (начиная с parent_id = 0), узлы с несуществующими родителями нам просто не вернутся из базы.
Цитата(mark2011 @  2.8.2011,  09:33 Найти цитируемый пост)
Такой вариант не работает однозначно, я проверил.

что мешает этому варианту работать?

Добавлено @ 10:05
http://codepad.org/dPYKaHtG

Это сообщение отредактировал(а) baldina - 2.8.2011, 10:24
PM MAIL   Вверх
baldina
Дата 2.8.2011, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(mark2011 @  2.8.2011,  09:33 Найти цитируемый пост)
где будет больше накладных расходов - при прохождении массивом, или прямым рекурсивным выводом из базы? 

нельзя сказать однозначно. зависит от размера данных, нагрузки на базу, нагрузки на сервер php.
по возможности всю работу целесообразно переложить на СУБД, выполняя иерархический запрос. Напрямую иерархические запросы могут не поддерживаться, это потребует программирования на стороне СУБД
PM MAIL   Вверх
нуп
Дата 2.8.2011, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ботокодер
**


Профиль
Группа: Участник
Сообщений: 987
Регистрация: 22.6.2009
Где: Кременчуг

Репутация: нет
Всего: 33



Да тупо кэшировать категории и всё  smile 
PM MAIL   Вверх
CruorVult
Дата 2.8.2011, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 868
Регистрация: 24.9.2008
Где: г.Киев, Украина

Репутация: 9
Всего: 28



Цитата(mark2011 @  2.8.2011,  09:33 Найти цитируемый пост)
С другой стороны, дерево может быть очень большое и массив может получиться огромный. Вот.... возникает вопрос, где будет больше накладных расходов - при прохождении массивом, или прямым рекурсивным выводом из базы?


А зачем вытаскивать всё дерево ? Если оно очень большое - юзеру думаю не в кайф будет листать всё. Обычно вытягивается верхний уровень и потом аяксом вытягивается нужные подкатегории.
PM MAIL Skype   Вверх
mark2011
Дата 2.8.2011, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 28.6.2011

Репутация: 2
Всего: 2



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

baldina
Ну по вашей логике: существует элемент с cat_id = 32, но не существует элемента parent_id = 32. Этот элемент лист - конец рекурсии. А элемент с cat_id = 33? Получается что он вообще не войдёт в выборку?
PM WWW ICQ Skype   Вверх
CruorVult
Дата 2.8.2011, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 868
Регистрация: 24.9.2008
Где: г.Киев, Украина

Репутация: 9
Всего: 28



Цитата(mark2011 @  2.8.2011,  11:41 Найти цитируемый пост)
А элемент с cat_id = 33? Получается что он вообще не войдёт в выборку?


с какого перепуга? Судя с дампа на рисунке cat_id = 33 он не имеет ни малейшего отношения к 32.

Да и вообще, вопрос по-моему уже ришен, просто вы никак не хотите начать думать smile 
PM MAIL Skype   Вверх
gcc
Дата 2.8.2011, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


Профиль
Группа: Участник
Сообщений: 2691
Регистрация: 25.4.2008
Где: %&й

Репутация: -1
Всего: 17



если таблица с одним деревом не 100гиг, то можно использовать Nested Set и еще примеры есть с innodb
PM WWW ICQ Skype GTalk Jabber   Вверх
baldina
Дата 2.8.2011, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 26
Всего: 101



Цитата(mark2011 @  2.8.2011,  11:41 Найти цитируемый пост)
существует элемент с cat_id = 32, но не существует элемента parent_id = 32. Этот элемент лист - конец рекурсии. 

да
Цитата(mark2011 @  2.8.2011,  11:41 Найти цитируемый пост)
А элемент с cat_id = 33? Получается что он вообще не войдёт в выборку?  

это от вас зависит, как вы хотите. или не войдет, или будет на верхнем уровне (как будто его parent_id=0)

вообще-то я все это уже говорил. и пример вам сделал, работающий с вашими данными

Добавлено через 57 секунд
http://codepad.org/dPYKaHtG смотрели?

Добавлено через 6 минут и 33 секунды
и вот это http://codepad.org/HwoD1QWJ
PM MAIL   Вверх
mark2011
Дата 19.10.2011, 13:22 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 28.6.2011

Репутация: 2
Всего: 2



Ну что ж, заново открываю мной же созданную тему...

Итак, структура базы данных та же. 
Вариант, предложенный Sanchezzz, после допиливания работает, но выдаёт следующее:

Цитата

Array
(
    [photo_category_id] => 1
    [photo_category_name] => 31
    [level] => 1
)
Array
(
    [photo_category_id] => 2
    [photo_category_name] => 32
    [level] => 1
)
Array
(
    [photo_category_id] => 3
    [photo_category_name] => 33
    [level] => 1
)
Array
(
    [photo_category_id] => 4
    [photo_category_name] => 34
    [level] => 1
)
Array
(
    [photo_category_id] => 11
    [photo_category_name] => 41
    [level] => 1
)
Array
(
    [photo_category_id] => 12
    [photo_category_name] => 42
    [level] => 1
)
Array
(
    [photo_category_id] => 13
    [photo_category_name] => 43
    [level] => 1
)
Array
(
    [photo_category_id] => 14
    [photo_category_name] => 44
    [level] => 1
)
Array
(
    [photo_category_id] => 5
    [photo_category_name] => 35
    [level] => 1
)
Array
(
    [photo_category_id] => 6
    [photo_category_name] => 36
    [level] => 1
)
Array
(
    [photo_category_id] => 7
    [photo_category_name] => 37
    [level] => 1
)
Array
(
    [photo_category_id] => 8
    [photo_category_name] => 38
    [level] => 1
)
Array
(
    [photo_category_id] => 9
    [photo_category_name] => 39
    [level] => 1
)
Array
(
    [photo_category_id] => 10
    [photo_category_name] => 40
    [level] => 1
)
Array
(
    [photo_category_id] => 15
    [photo_category_name] => 45
    [level] => 1
)


Т.е. как бы нормально, НО:

Почему-то уровень всё время первый, т.е. невозможно однозначно отследить где начинается потомок. Вот мой допиленный код:
Код

function Tree($id=0, $level=0, $i=0) {
$s = "SELECT photo_category_id, photo_category_name FROM photo_browser_categories WHERE photo_category_parent_id = '" . $id . "'";
$res = mysql_query($s);

if( mysql_num_rows($res) > 0){
        $level++;    
        while($r = mysql_fetch_assoc($res)){
            $i++;
            $r['level'] = $level;
            print_R($r);
            Tree($r['photo_category_id']);
            
        }
    }else{
        $level--;
    }
}

PM WWW ICQ Skype   Вверх
MoLeX
Дата 19.10.2011, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140





--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
mark2011
Дата 20.10.2011, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 28.6.2011

Репутация: 2
Всего: 2



Я не могу использовать вложенные множества. Во-первых это потребует изменения структуры таблицы, во вторых у меня не такое разветвлённое дерево. Изменять структуру таблицы не нужно.
PM WWW ICQ Skype   Вверх
MoLeX
Дата 20.10.2011, 08:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



mark2011, плодите тогда запросы к СУБД. Это ваше право, наше дело предложить


--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0616 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.