Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Построение навигации средствами Mysql / 13 сообщений из 13, страница 1 из 1
17.08.2005, 11:32:27
    #33219979
Black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Добрый день уважаемый all.
есть таблица

id|pod_id|name
2 | 1 | Литература
1 | null | Главная
3 | 2 | Остров сокровищь
....

тут pod_id внешинй ключ ссылающийся на первичный ключ id
Мне надо, сделать древовидный запрос, начиная, например, с id=3 , что бы получилось:
Остров сокровищь
Литература
Главная


В навигации это будет выглядеть как:
Главная - Литература - Остров сокровищь

Сам работал всегда с Oracle, там есть функции решающий данную задачю connect by, start with.

Возможно ли решить данную задачю средства Mysql?
Заранее благодарен за помощь!
...
Рейтинг: 0 / 0
17.08.2005, 12:37:24
    #33220235
Berkut
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Николай aka MotodorOracle, там есть функции решающий данную задачю connect by, start with.

Возможно ли решить данную задачю средства Mysql?К сожалению в MySQL'е пока что нет аналогичных средств для работы с иерархическими структурами данных. На официальном сайте MySQL видел, что это планируется в какой-то 5-ой версии СУБД.

Деревья в поддерживающих стандарты SQL базах данных
...
Рейтинг: 0 / 0
22.08.2005, 14:45:05
    #33228044
Построение навигации средствами Mysql
http://forum.dklab.ru/php/heap/empty_15.html

посмотри, до чего я дошел...
сейчас в реальности структура немного изменилась, но смысл остался
...
Рейтинг: 0 / 0
24.08.2005, 12:35:59
    #33231587
Astron
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Николай aka Motodor
Сам работал всегда с Oracle, там есть функции решающий данную задачю connect by, start with.

Возможно ли решить данную задачю средства Mysql?
Заранее благодарен за помощь!

Сегодня прислали с рассылкой

Достижения MySQL по этому поводу
...
Рейтинг: 0 / 0
24.08.2005, 12:54:30
    #33231636
Black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Спасибо за ссылки, сейчас почитаю ...
...
Рейтинг: 0 / 0
24.08.2005, 13:06:51
    #33231669
Berkut
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
AstronСегодня прислали с рассылкой

Достижения MySQL по этому поводу
Да только они не уточняют, что при построении дерева ("Retrieving a Full Tree") для выполнения этой операции кол-во LEFT JOIN прямопропорционально кол-ву "уровней вложенности" - 1.
Другими словами, если захочется добавить нового потомка в дерево, "уровень вложенности" которого будет на единицу больше "уровней вложенности" остальных узлов, то придется "ручками" еще дописывать одно LEFT JOIN. ;)

P.S. Хорошо конечно, когда есть хоть что-то, но имхо MySQL уже пора делать поддержку для работы с иерархическими структурами данных.
...
Рейтинг: 0 / 0
24.08.2005, 19:00:16
    #33232702
Astron
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Berkut Да только они не уточняют, что при построении дерева ("Retrieving a Full Tree") для выполнения этой операции кол-во LEFT JOIN прямопропорционально кол-ву "уровней вложенности" - 1.
Другими словами, если захочется добавить нового потомка в дерево, "уровень вложенности" которого будет на единицу больше "уровней вложенности" остальных узлов, то придется "ручками" еще дописывать одно LEFT JOIN. ;)

P.S. Хорошо конечно, когда есть хоть что-то, но имхо MySQL уже пора делать поддержку для работы с иерархическими структурами данных.

Не, ну тогда делайте так - я просто не написал сразу в силу очевидности решения....
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
use astron;

create table for_tree_tbl (id int not null primary key, parent_id int, str_val varchar( 20 ));

insert into for_tree_tbl values 
  ( 1 ,null, 'root'),
  ( 2 , 1 ,'first level child 1'), 
  ( 3 , 1 , 'first level child 2'),
  ( 4 , 2 ,'second level child 1'),
  ( 5 , 2 ,'thrid level child 1');

SELECT for_tree_tbl.* 
FROM
 for_tree_tbl,
(
  SELECT parent_id AS parent,
         id AS child
    FROM for_tree_tbl
   WHERE parent_id IS NULL
   UNION ALL 
  SELECT t2.parent_id AS parent,
         t2.id AS child
    FROM for_tree_tbl t1, for_tree_tbl t2
   WHERE t1.id=t2.parent_id
 ) ftbl
WHERE for_tree_tbl.id=ftbl.child;
...
Рейтинг: 0 / 0
24.08.2005, 19:10:53
    #33232717
Astron
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
А, понял почему вопрос! Я когда на Oracle работал, тоже так не умел :-)

Кстати, в предыдущем посте неточность, элемент 3-го уровня вставляется на 2-й, надо
Код: plaintext
1.
2.
...
( 5 , 4 ,'thrid level child 1');
...
ну я думаю это не принципиально. Так что поддержка есть начиная с 4.1.
...
Рейтинг: 0 / 0
25.08.2005, 10:46:04
    #33233391
Berkut
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
2 Astron
Может я не совсем догоняю Вашу мысль, но запрос не дает визуального представления дерева. Т.е. при выводе данных не сохраняются рекурсивные зависимости parent_id - id. Возможно это просто неуданый пример.

Позвольте немного изменить ваш запрос (для наглядности).

Код: plaintext
Добавим нового потомка на второй уровень
Код: plaintext
1.
insert into for_tree_tbl values ( 6 , 3 , 'second level child 2')

Код: plaintext
Добавим новое поле  level  в таблицу
Код: plaintext
1.
2.
3.
4.
5.
alter table for_tree_tbl add level tinyint not null default  0 

update for_tree_tbl set level= 1  where id= 2  or id= 3 ;
update for_tree_tbl set level= 2  where id= 4  or id= 6 ;
update for_tree_tbl set level= 3  where id= 5 ;

Код: plaintext
Таким образом дерево выглядит следующим образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
str_val                                 id  parent_id
----------------------------------  ------  ---------
+ root                                      1    (NULL)  
|
+----+ first level child 1                 2          1
     |
     +----+ second level child 1           4          2
     |    |
     |    +----- thrid level child 1       5          4
     |
     +----+ first level child 2            3          1
          |
          +----- second level child 2      6          3

Запрос, который Вы превели выше выводит следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
SELECT LPAD(for_tree_tbl.str_val, LENGTH(for_tree_tbl.str_val)+ 5 *for_tree_tbl.level, ' ') str_val, 
       for_tree_tbl.id,
       for_tree_tbl.parent_id
FROM
 for_tree_tbl,
(
  SELECT parent_id AS parent,
         id AS child
    FROM for_tree_tbl
   WHERE parent_id IS NULL
   UNION ALL 
  SELECT t2.parent_id AS parent,
         t2.id AS child
    FROM for_tree_tbl t1, for_tree_tbl t2
   WHERE t1.id=t2.parent_id
 ) ftbl
WHERE for_tree_tbl.id=ftbl.child

str_val                                 id  parent_id
----------------------------------  ------  ---------
root                                      1    (NULL)  
     first level child  1                   2            1 
     first level child  2                   3            1 
          second level child  1             4            2 
               thrid level child  1         5            4 
          second level child  2             6            3 

Данный запрос выводит тоже самое:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SELECT LPAD(for_tree_tbl.str_val, LENGTH(for_tree_tbl.str_val)+ 5 *for_tree_tbl.level, ' ') str_val, 
       for_tree_tbl.id,
       for_tree_tbl.parent_id
  FROM for_tree_tbl

str_val                                 id  parent_id
----------------------------------  ------  ---------
root                                      1    (NULL)  
     first level child  1                   2            1 
     first level child  2                   3            1 
          second level child  1             4            2 
               thrid level child  1         5            4 
          second level child  2             6            3 

Зачем тогда вложенный селект?
...
Рейтинг: 0 / 0
25.08.2005, 12:49:34
    #33233905
Валентин К
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Внимательно пока статью не читал, но посмотрев запросы - не получится нормального визуализирования.

Вообще подход к визуализации дерева с ключем и ссылкой на владельца можно осуществить только рекурсивно, что пока невозможно реализовать даже в версии 5.0, тем более что с версии 5.0.10, если не ошибаюсь даже рекурсию выключили (временно) в процедурах.
...
Рейтинг: 0 / 0
25.08.2005, 14:15:32
    #33234204
Astron
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Ну во-первых извиняюсь за мелкую ошибку в подзапросе.
Ниже видно какая.
Во-вторых я не стремился визуализировать дерево, я делал аналог оракловых START WITH - CONNECT BY
После ваших апдейтов слегка модифицированный запрос выдает следующее,
что соответствует результату оракловой конструкции.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
mysql> use astron
Database changed
mysql> SELECT
    ->        for_tree_tbl.level,
    ->        ftbl.parent_name,
    ->        for_tree_tbl.str_val
    -> FROM
    ->  for_tree_tbl,
    -> (
    ->   SELECT parent_id AS parent,
    ->          id AS child,
    ->          null as parent_name
    ->     FROM for_tree_tbl
    ->    WHERE parent_id IS NULL
    ->    UNION ALL
    ->   SELECT t2.parent_id AS parent,
    ->          t2.id AS child,
    ->          t1.str_val as parent_name
    ->     FROM for_tree_tbl t1, for_tree_tbl t2
    ->    WHERE t1.id=t2.parent_id
    ->  ) ftbl
    -> WHERE for_tree_tbl.id=ftbl.child;
+-------+----------------------+----------------------+
| level | parent_name          | str_val              |
+-------+----------------------+----------------------+
|      0  | NULL                 | root                 |
|      1  | root                 | first level child  1   |
|      1  | root                 | first level child  2   |
|      2  | first level child  1   | second level child  1  |
|      3  | second level child  1  | thrid level child  1   |
+-------+----------------------+----------------------+
 5  rows in set ( 0 . 00  sec)
...
Рейтинг: 0 / 0
25.08.2005, 15:26:18
    #33234379
Astron
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
Внимательно прочитал первый пост - автору нужно ПОДНЯТЬСЯ по дереву, а это уже совсем другая песня, да... Тут без PREV ораклового не обойтись, действительно. Это спускаться по дереву можно с любого места, хоть с подзапросом хоть без, а вверх разве что принять что ID парента всегда меньше чайлда и ограничить это в условии. Получив при этом кучу лишнего, разумеется, и фильтровать это уже на клиенте...
...
Рейтинг: 0 / 0
26.08.2005, 17:34:08
    #33236854
Валентин К
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Построение навигации средствами Mysql
И я вот еще чего не пойму...
В чем собственно проблема?

> Есть таблицу с древовидной структурой Tree.
> Поля таблицы Tree:
> ID (целое) - идентификатор объекта
> ParentID (целое) - идентификатор "родителя", если верхний уровень, то 0
> Level (целое) - уровень объекта, самый верхний - 0, делее 1,2....
> Path (строка) - самое интересное :) список идентификаторов ВСЕХ родителей через запятую (например 23,15,46,12). Порядок в списке особо не важен
>
> Запрос пути:
> SELECT .... FROM Tree WHERE FIND_IN_SET(ID,ObjPath) ORDER BY Level
>
> ObjPath - поле Path обекта, путь к котрому надо найти. Если известен только ID объекта, тогда придется сделать два запроса
>
> SELECT @ObjPath:=Path FROM Tree WHERE ID=ObjID;
> SELECT .... FROM Tree WHERE FIND_IN_SET(ID,@ObjPath) ORDER BY Level;
>
> В результате получим таблицу - список родителей начиная с самого верхнего, заканчивая самым последним.
> Для автоматического формирования полей Level и Path при вставке(переименовании, удалении) можно использовать триггеры или, как это сделал я, написать код в языке программирования.
>
> Воть. Ничего особенного в этом способе нет. Как выяснилось позже, этот способ давно найден и успешно эксплуатируется. А я его повторно "открыл". Вывод - надо лучше искать в Интернете :).
>
> P.S. А может есть способ проще? :)
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Построение навигации средствами Mysql / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]