Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вывести всех родитеей дерева 
:(
    Опции темы
gcc
Дата 3.5.2009, 06:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



нужно вывести всех родителей дерева их id и name?  MySQL
ни где не нашел это

есть столбцы:  id | parent_id | name

сделал рекурсию в скрипте, вывесло, но делает больше 5-10 запросав, сказал что не правильно...

как лучше всего? сделать процедуру в MySQL или еще как-то можно?

может включить кэширвоание и сделать рекурсию обычную? кэширование спасет? оно не будет повтороно для каждого родителя делать запрос?



Это сообщение отредактировал(а) gcc - 3.5.2009, 10:16
PM WWW ICQ Skype GTalk Jabber   Вверх
gcc
Дата 3.5.2009, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



вот нашел
http://cpansearch.perl.org/src/BJEPS/DBIx-Tree-1.9/Tree.pm

оно по-моиму без рекурсии, там можно указать start_id

оно сразу всю таблицу вытаскивает? если да, то это не подхожит...


UPD: нашел http://www.getinfo.ru/article610.html

Это сообщение отредактировал(а) gcc - 3.5.2009, 10:17
PM WWW ICQ Skype GTalk Jabber   Вверх
skyboy
Дата 3.5.2009, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



есть два простых решения: не химичить с тем, что не подходит smile
либо сменить стрктуру хранения на nested sets, либо добавить в каждую запись поле, в котором серализированно хранить идентификаторы всех предков(например, так: "00001.00005.00015.00128").  в обоих случаях для выбора родителей рекурсия не будет нужна.
PM MAIL   Вверх
gcc
Дата 31.7.2009, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



skyboy, при серилизации как мне вывести дерево, точнее всех под разделов с указаного раздела, одим или нескольким запросами?

==============

использую MySQL, MyISA

NestedSet не понравился, говорят он ресурсовемкий если таблица большая, не зря придумывали много для дерева в FriBide, Oracle, etc

и таблицу я создал только c parent_id
если добавить сейчас NestedSet , то переписывать прейдется

не плохой вариант: серилизировать всех родителей каждого дерева

очень замечательно, можно переносить разделы, добавлять в любой раздел, ресурсов оно не затребует, несколько UPDATE - можно вставить один запросом, если я правильно понимаю...

может есть смысл innoDB использовать с внешними ключами? только елси там есть реально решения... если оно там есть?
или какой вариант лучше?

Это сообщение отредактировал(а) gcc - 31.7.2009, 15:23
PM WWW ICQ Skype GTalk Jabber   Вверх
skyboy
Дата 31.7.2009, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



Цитата(gcc @  31.7.2009,  14:15 Найти цитируемый пост)
как мне вывести дерево, точнее всех под разделов с указаного раздела, одим или нескольким запросами?

Вывожу потомков раздела с "00007"(типичное значение поля parents: "00003.00007.00010"):
Код

SELECT *
fROM tree
WHERE locate(".00007.",concat(".",parents,"."))> 0

но этот вариант напряжен при выборке: в отличие от одного поля parent_id и пары left_id+right_id в nested sets, сериализированный путь - не индексированное числовое поле. Потому разница в скорости выборки для сериализированного пути и других вариантов должно отличаться уже для небольшого количества элементов(в тысячах), правда, экспериментом подтвердить не могу.
PM MAIL   Вверх
gcc
Дата 31.7.2009, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



я думал что нужно серилизировать только вершние разделы, например от 0007

0001
     0004
        0007

надо нижние тоже серилизировать, а как нижние серилизировать? создаю я подраздел в каком-то разделе, как мне узнать все нижние? ( если всего разделов 1000 и больше, то нужно 1000 UPDATE одним запросом сделать?) (верхние понятно - у родителя)

а есть ли документация? 

я не нашле http://www.google.com.ua/search?hl=uk&...%8C&spell=1





Это сообщение отредактировал(а) gcc - 31.7.2009, 15:44
PM WWW ICQ Skype GTalk Jabber   Вверх
Zloxa
Дата 31.7.2009, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Nested Sets очень плох на модификации данных. Многопользовательское редактирование можно забыть. Зато дает быстрый селект.
Хранение полного пути к ноде(ранее было, как я понял, названо сериализацией) - одинаково плохо как на выборке, так и на редактировании. Не снимает порбемы многоползовательской модификации.
Самый компромиссный вариант - рекурсия с клиента или хп.
однако не понятно кто "сказал что не правильно" и чем "он" руководствовался.

Это сообщение отредактировал(а) Zloxa - 31.7.2009, 15:50


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
gcc
Дата 31.7.2009, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



ладно тогда nested sets

я вот нашел новые стать:
(не много по другому сделано)
http://habrahabr.ru/blogs/perl/65495/

вот есть на триггерах:
http://habrahabr.ru/blogs/mysql/63883/
http://habrahabr.ru/blogs/postgresql/63416/

не много старые
http://doc.prototypes.ru/database/nestedsets/perl/module/
http://webscript.ru/stories/04/09/01/8197045
PM WWW ICQ Skype GTalk Jabber   Вверх
skyboy
Дата 31.7.2009, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



Цитата(gcc @  31.7.2009,  14:38 Найти цитируемый пост)
надо нижние тоже серилизировать, а как нижние серилизировать?

нет, конечно.
я тебе привел пример запроса выбора всех непосредственных и косвенных потомков.

PM MAIL   Вверх
gcc
Дата 1.8.2009, 06:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



я вот нашел что Firebird хратит ссылку родительский узел

Firebird будет лучше? она бесплтаная вродебы, есть на Linux и FreeBSD 

http://gsbelarus.com/gs/modules.php?name=N...cle&sid=314

Цитата

самый простой способ представления дерева в реляционной базе — это помещение матрицы смежности в таблицу. Каждая запись такой таблицы соответствует узлу дерева и хранит его уникальный идентификатор и ссылку на родительский узел.

Ниже приведен DDL запрос для создания таблицы TEST1 (щелкните по тексту запроса для загрузки его текста в браузер):

CREATE TABLE test1 (
  id INTEGER NOT NULL,
  parent INTEGER,
  
  PRIMARY KEY (id),
  FOREIGN KEY (parent) REFERENCES test1 (id)
    ON UPDATE CASCADE
    ON DELETE CASCADE
);

Обратите внимание на правило ON DELETE CASCADE, заданное для внешнего ключа по полю PARENT. Благодаря нему, при удалении узла будет автоматически удалено и все поддерево, для которого этот узел является корнем. 

PM WWW ICQ Skype GTalk Jabber   Вверх
skyboy
Дата 1.8.2009, 08:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



Цитата(gcc @  1.8.2009,  05:16 Найти цитируемый пост)
я вот нашел что Firebird хратит ссылку родительский узел

ты показываешь такую же стурктуру, о которой говорил в своем первом посте.
PM MAIL   Вверх
gcc
Дата 1.8.2009, 09:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



в первом посте нету
Код

  FOREIGN KEY (parent) REFERENCES test1 (id)
    ON UPDATE CASCADE
    ON DELETE CASCADE
); 


и в первом посте кроме рекурсии практически никак нельзя вынуть вверхние или нижние...?

а тут для извлечения всех потомков узла Р и всех потомков потомков
Код

SELECT id
FROM
  test1
WHERE
  parent = :P
  
UNION
  
SELECT t1.id
FROM
  test1 t1 JOIN test1 t2
    ON t1.parent = t2.id
WHERE
  t2.parent = :P


а чтобы все вложенные уровни для узла с идентификатором, заданным параметром Р

Код

CREATE PROCEDURE RecTest1(AnID INTEGER, Self INTEGER)
  RETURNS (ID INTEGER)
AS
BEGIN
  IF (:Self <> 0) THEN
  BEGIN
    ID = :AnID;
    SUSPEND;
  END
  
  FOR SELECT id FROM test1
  WHERE parent = :AnID INTO :ID
    DO FOR SELECT id FROM RecTest1(:ID, 1) INTO :ID
      DO SUSPEND;
END;

================================

SELECT t.*
FROM test1 t
  JOIN RecTest1(:P, 0) r ON t.id = r.id



там написано что Firebird может рекурсивно это сделать:
Многие сервера баз данных имеют ограничение на максимальное количество рекурсивных вызовов процедуры. Например, для Firebird это ограничение составляет порядка одной тысячи, чего, впрочем, более чем достаточно для выполнения большинства задач

PM WWW ICQ Skype GTalk Jabber   Вверх
skyboy
Дата 1.8.2009, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


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

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



Цитата(gcc @  1.8.2009,  08:10 Найти цитируемый пост)
в первом посте нету

ну, так тебе ничто не мешает и под mysql использовать foreign key для каскадного удаления всех потомков при удалении родителя.
Цитата(gcc @  1.8.2009,  08:10 Найти цитируемый пост)
и в первом посте кроме рекурсии практически никак нельзя вынуть вверхние или нижние...?

перебор неограниченной глубины связей можно либо через итерации(через курсоры, видимо, чтоб средствами sql), либо через рекурсию. и твой приведенный запрос для выбора потомков и потомков потомков будет иметь одинаковую функциональность что в firebird, что в mysql. 
если в какой-то СУБД и есть специальный структуры для хранения/обработки графов/деревьев, то пока что про них не было сказано ни слова - список смежности(в виде поля parent_id), сериализацию пути("00001.00008.00010") и Nested Sets можно реализовать в любой СУБД. будь то Firebird или mysql.
и, да, в чем у тебя вопрос? на вопрос 
Цитата(gcc @  3.5.2009,  05:57 Найти цитируемый пост)
как лучше всего?

тебе Zloxa, привел аргументы касательно 3 способов. 
кроме того: ты ищешь "лучшую"(по каким параметрам?) реализацию хранения графа под определенную СУБД(MySQL, судя по первому посту) или ты выбираешь СУБД под хранение графа(то MySQL, то Firebird)?
PM MAIL   Вверх
gcc
Дата 1.8.2009, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(skyboy @ 1.8.2009,  13:10)
кроме того: ты ищешь "лучшую"(по каким параметрам?) реализацию хранения графа под определенную СУБД(MySQL, судя по первому посту)

да, я уже выбрал - это NestedSet либо рекурсия, просто хотел спросить, может есть что-то другое, если была СУБД в которой были бы опреаторы для работы с деревом я бы выбрал ее... и с начало надо подумать над архитектурой БД, правильно? например, не рекоммендуется в MySQL использовать рекурсию...

а как этот запрос написать в MySQL чтобы посмотреть всех родителей ввреху (не дерево выводить, а иммено родителей)?
Код

SELECT id
FROM
  test1
WHERE
  parent = :P
  
UNION
  
SELECT t1.id
FROM
  test1 t1 JOIN test1 t2
    ON t1.parent = t2.id
WHERE
  t2.parent = :P

 
не много не понял  parent = :P это тоже самое что и   parent = $p

еще что-то не смог придумать запрос, если у каждого раздела есть поле active (0 или 1 значение)  как изменить у всех подразделов поле active на 1 (тут скорее всего NestedSet...)


Это сообщение отредактировал(а) gcc - 1.8.2009, 13:34
PM WWW ICQ Skype GTalk Jabber   Вверх
Zloxa
Дата 1.8.2009, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(gcc @  1.8.2009,  13:32 Найти цитируемый пост)
если была СУБД в которой были бы опреаторы для работы с деревом я бы выбрал ее...

Ты же сам упомянул об этих СУБД


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




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


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

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