Автор Тема: Обсуждение статьи ДЕРЕВО КАТАЛОГОВ NESTED SETS (ВЛОЖЕННЫЕ МНОЖЕСТВА) И УПРАВЛЕНИЕ ИМ  (Прочитано 40436 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Phoinix

  • RW
  • Ветеран
  • *****
  • Сообщений: 1097
  • +0/-0
  • 2
    • Просмотр профиля
    • http://phoinix.ucoz.ru
Гость
Что-то не вижу никакой проблемы в решении данного вопроса...

Есть запрос для получения родителя узла:

SELECT id
FROM my_table
WHERE t2.left_key < t1.left_key AND t2.right_key > t1.right_key AND t2.level = t1.level - 1

Есть запрос выборки всех узлов:

SELECT id
FROM my_table
ORDER BY left_key

Объединяем 2 запроса:

SELECT t1.id AS id, t2.id AS parent
FROM my_table AS t1
LEFT JOIN my_table AS t2
ON t2.left_key < t1.left_key AND t2.right_key > t1.right_key AND t2.level = t1.level - 1
ORDER BY t1.left_key

Соответственно если родителя нет - parent = NULL

Гость

  • Гость

Оффлайн APL

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 344
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.aerozone.ru
2 Phoinix

Цитировать
Поэтому я сделал свое решение, которое позволяет 1 запросом перемещать узел в любую точку дерева...


Нельзя ли поподробнее? Если можно с примером...

Спасибо.

Оффлайн Piter-G

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 16
  • +0/-0
  • 0
    • Просмотр профиля
    • http://skitalets.ru
а если мы удаляем и добавляем узел не в конец ветки,  а где-нибудь посередине.

тогда при удалении нужно добавить для подчиненных узлов:

UPDATE my_tree SET right_key = right_key – 1,  left_key = left_key – 1WHERE right_key < $right_key AND left_key > $left_key

при добавлении для подчиненных узлов:

UPDATE my_tree SET right_key = right_key + 1,  left_key = left_key + 1WHERE right_key < $right_key AND left_key > $left_key

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

Оффлайн Phoinix

  • RW
  • Ветеран
  • *****
  • Сообщений: 1097
  • +0/-0
  • 2
    • Просмотр профиля
    • http://phoinix.ucoz.ru
Piter-G
Цитировать
тогда при удалении нужно добавить для подчиненных узлов:


Обычно удаляется вся ветка, поэтому, обновление для подчиненных узлов - не нужно...

Цитировать
при добавлении для подчиненных узлов:


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

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


Не верно... все делается гораздо проще...

Оффлайн Piter-G

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 16
  • +0/-0
  • 0
    • Просмотр профиля
    • http://skitalets.ru
To Phoinix

Цитировать
Это как? ты добавляешь узел сразу с подчиненными узлами?


Нет, я вставляю узел за каким-то определенным узлом. У этого узла могут быть и подчиненные узлы. Тогда их нужно переподчинить вновь вставляемому узлу.
« Последнее редактирование: 30 Октября 2004, 22:18:32 от Piter-G »

Оффлайн Phoinix

  • RW
  • Ветеран
  • *****
  • Сообщений: 1097
  • +0/-0
  • 2
    • Просмотр профиля
    • http://phoinix.ucoz.ru
Piter-G
Вообще-то не только их, я все дерево следующее за местом вставки элемента

Оффлайн Piter-G

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 16
  • +0/-0
  • 0
    • Просмотр профиля
    • http://skitalets.ru
Phoinix

Ну, конечно, ты прав, это же очевидно. Я эти узлы и имел ввиду под подчиненными. Да и по поводу перемещения ты, наверное, прав. Так, как  это описано в статье, действительно, может и не проще для понимания, но правильней.

Simon

  • Гость
Цитировать
Гость:
Пока что делаю так

1)Запрашиваю список всех разделов
2)Для каждого раздела отдельным запросом определяю ID родителя.


Выложи вкратце оба своих запроса, а мы их сошьём :)

Simon

  • Гость
Цитировать
Simon:
Выложи вкратце оба своих запроса, а мы их сошьём

Пардону прошу, второй странички форума не заметил ;)

Оффлайн CLiI{er

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 57
  • +0/-0
  • 0
    • Просмотр профиля
    • http://glossword.info/
Статья на редкость интересная. Не в том смысле, что интересные фрагменты встречаются редко.

Порадовали конкретные SQL-запросы для выполнения конкретных задач.
Скажите, а кто-либо использует эту схему для своих сайтов?

Интересует, как nested sets можно сравнить со схемой, которая применяется для GForge (http://gforge.org/):

id_topic
    Номер узла, auto_increment, наш primary key.
sort_order
    Порядок сортировки, +/- 10.
id_parent
    Вышестоящий узел.
id_parent_root
    Вышестоящий узел второго уровня вложенности. Если для данного узла такого уровня нет - тогда 0.
cnt_subtopic
    Количество узлов внутри данного узла. Для вывода на экран "тема такая-то (10)"
ids_fullpath
    Полный путь узла, разделенный каким-нибудь простым способом. Например запись " 10 :: 23 :: 45 " означает "45-й узел внутри 23-го, 23-й внутри 10-го, 10-й - самый главный и он же в id_parent_root)

Выбор фрагмента ветки любого уровня производится с помощью запроса:

SELECT ids_fullpath FROM table
WHERE ids_fullpath LIKE "% 23 %"

Пример полученного списка:

10 :: 23
10 :: 23 :: 45
10 :: 23 :: 45 :: 50

Выбор всей ветки:

SELECT ids_fullpath FROM table
WHERE id_parent_root = "10"

Обновление и добавление несложное - одна php-функция просто добавляет строку
без ids_fullpath, другая - рекурсивная, пересчитывает ids_fullpath
для только что вставленного id_topic и, если потребуется, для всей ветки, начиная c последнего узла (45),
заканчивая первым, root (10).

Содержимое таблицы:

id_topic id_parent id_parent_root cnt_subtopic ids_fullpath
10       0         0              3            10
23       10        10             2            10 :: 23
45       23        10             1            10 :: 23 :: 45
50       45        10             0            10 :: 23 :: 45 :: 50

Примерно такая схема применяется сегодня на sourceforge.net, freshmeat.net.
Только там базы PostgreSQL, поэтому значение для поля cnt_subtopic
вычисляется автоматически при обновлении дерева с помощью хранимой процедуры.
« Последнее редактирование: 04 Ноября 2004, 01:48:14 от CLiI{er »
gw веб-песочница жж

Оффлайн Phoinix

  • RW
  • Ветеран
  • *****
  • Сообщений: 1097
  • +0/-0
  • 2
    • Просмотр профиля
    • http://phoinix.ucoz.ru
CLiI{er
Цитировать
Скажите, а кто-либо использует эту схему для своих сайтов?


Странный вопрос, тем более что я внизу написал даже на каких... ;)

А по сравнению:
Цитировать
Обновление и добавление несложное - одна php-функция просто добавляет строку
без ids_fullpath, другая - рекурсивная, пересчитывает ids_fullpath
для только что вставленного id_topic и, если потребуется, для всей ветки, начиная c последнего узла (45),
заканчивая первым, root (10).


При использовании Nested Set - достаточно одного запроса при обновлении (перемещении), и трех, при добавлении:
UPDATE дерева
INSERT узла

Впрочем это все написано и так в статье...

То же самое с выбором фрагмента ветки, хотя, у тебя это тоже один запрос, но использовать LIKE - несколько медленно

А если хочется выбрать и родительскую ветку и подчиненные узлы сразу?

Оффлайн CLiI{er

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 57
  • +0/-0
  • 0
    • Просмотр профиля
    • http://glossword.info/
Цитировать
Phoinix:
я внизу написал даже на каких...


Это сайты автора статьи. Разница между рекламными ссылками и применением предложенной схемы другими разработчиками в производстве сайтов всё же существует. О применении я и хотел услышать. И, если возможно, узнать, какие коммерческие продукты используют nested sets (я просто не в курсе).
gw веб-песочница жж

Гость

  • Гость
Может я че-то не понимаю .. но что-то мне кажеться что этf система постороение дерева не быстрее обычной .. где ID и Parent_ID ...

Оффлайн Phoinix

  • RW
  • Ветеран
  • *****
  • Сообщений: 1097
  • +0/-0
  • 2
    • Просмотр профиля
    • http://phoinix.ucoz.ru
Гость
Цитировать
что эта система постороение дерева не быстрее обычной

Может я тоже что-то не понимаю, но при чем тут построение дерева и скорость?

 

Sitemap 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