деревовидные связи

MySQL/PostgreSQL/SQLite/Oracle/M$SQL/....

Модератор: terminus

Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 7:28:50

у меня есть столбцы:

Код: Выделить всё

id | parent_id | name
как тут более оптимально? процедуру сделать? или рекурсию в скрипте? (про рекурсию в скрипте сказали что это не праильно)
дургие СУБД поддерживают рекурсию...

нашел пример:

для такой таблицы:
Изображение

вернет это:
Изображение

такой запрос

Код: Выделить всё

SELECT 
    T.ID,
    T.ID_PARENT,
    T."VALUE"
FROM T
    WHERE T."LEVEL"=0
    AND T.ID IN (2,5)
UNION
SELECT 
    FI.ID,
    FI.ID_PARENT,
    FI."VALUE"
FROM T
INNER JOIN (
    SELECT 
        ID,
        ID_PARENT,
        "VALUE"
    FROM T
        WHERE "LEVEL"=1
    )  AS FI 
    ON T.ID=FI.ID_PARENT
    WHERE T."LEVEL"=0
    AND T.ID IN (2,5)
UNION
SELECT 
    SI.ID,
    SI.ID_PARENT,
    SI."VALUE"
FROM T
INNER JOIN (
    SELECT 
        ID,
        ID_PARENT,
        "VALUE"
    FROM T
        WHERE "LEVEL"=1
    )  AS FI 
    ON T.ID=FI.ID_PARENT
    INNER JOIN (
        SELECT 
            ID,
            ID_PARENT,
            "VALUE"
        FROM T
            WHERE "LEVEL"=2
        ) AS SI
        ON FI.ID=SI.ID_PARENT
        WHERE T."LEVEL"=0
        AND T.ID IN (2,5);
http://forum.vingrad.ru/forum/topic-257734.html
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-03 7:37:00

ProFTP писал(а):такой запрос
бред
ProFTP писал(а):как тут более оптимально?
если записей меньше тысячи, то выбираешь их все и строишь дерево силами ЯП

а так лучшей сипользуй метод с левой-правой стороной

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 7:42:47

zg писал(а): выбираешь их все и строишь дерево силами ЯП
я про это не подумал, но тем не меннее дерево большое расчитывается, я вот пишу управление деревром, сайт/форум в котром разделы будут деревом

то есть под разделов (родителей) от 5 до 10 и более...

или может я не правильно архитектуру написал (выбрал)? может дерерво не надо?
я решил сделать дерево, чтобы можно было создать много подразделов...

тогда пока попробую процедуру в MySQL, остановлю на этом, но это значит что она сделат у себя несколько запросов (штук 5-10-15 через while), и будет быстрее скорее всего?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-03 7:54:14

ProFTP писал(а):сайт/форум в котром разделы будут деревом
тогда тебе прямой путь к левой-правой стороне потому, что это самый оптимальный и быстрый способ выбор целевых записей
ProFTP писал(а):тогда пока попробую процедуру в MySQL, остановлю на этом, но это значит что она сделат у себя несколько запросов (штук 5-10-15 через while), и будет быстрее скорее всего?
нет

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 7:57:03

про ORM: у меня она не стоит сейчас, не использую

вот тут пример, правда дургой: http://forum.vingrad.ru/index.php?showt ... &p=1778273

но не опнятно поможет ли она или нет... (ей можно сделать запросов ОО штук 20, а она обработва, автоматически сделает 2-4 говорят)
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 7:58:26

zg писал(а): тогда тебе прямой путь к левой-правой стороне потому
что это такое? не нашел
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 8:05:12

а если кэширование работает, кэширует запросы, может оно спасет?
так как разделы врядли будут менятся часто, все будет лежат ьв хранилище share memory и от туда братся
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-03 8:57:59

ProFTP писал(а):а если кэширование работает, кэширует запросы, может оно спасет?
от структурных ошибок не спасёт
ProFTP писал(а):что это такое? не нашел
MAK выкладывал в этой теме

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-05-03 18:03:40

вот еще нашел, можно серализированно хранить идентификаторы всех предков(например, так: "00001.00005.00015.00128")
тоже не плохой вариант
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-03 18:19:41

ProFTP писал(а):тоже не плохой вариант
при таком варианте трудно сохранить целостность базы, если вдруг чё-то слетит. Хотя, у меня такой вариант пашет :smile:

ev
ст. лейтенант
Сообщения: 1325
Зарегистрирован: 2008-07-27 17:11:30
Откуда: Москва

Re: деревовидные связи

Непрочитанное сообщение ev » 2009-05-03 18:59:30

при таком варианте трудно сохранить целостность базы, если вдруг чё-то слетит. Хотя, у меня такой вариант пашет :smile:
да не... просто... делаешь верификацию (пробежку по дереву) и все восстанавливается
сам так делал :) получается что-то вроде кеширования

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-03 19:09:37

ev писал(а):делаешь верификацию (пробежку по дереву) и все восстанавливается
вопрос только каким данным изначально доверять :smile: если только номеру родителя то лекго получить зацикливание.

ev
ст. лейтенант
Сообщения: 1325
Зарегистрирован: 2008-07-27 17:11:30
Откуда: Москва

Re: деревовидные связи

Непрочитанное сообщение ev » 2009-05-03 20:12:24

ну если побилось все, и имена тоже - то любой алгоритм не поможет :cz2:

zg
полковник
Сообщения: 5845
Зарегистрирован: 2007-12-07 13:51:33
Откуда: Верх-Нейвинск

Re: деревовидные связи

Непрочитанное сообщение zg » 2009-05-04 8:01:34

ev писал(а):ну если побилось все
зачем всё -)) просто, данные одной записи могут противоречить друг другу.

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-07-31 15:11:58

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

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

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

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

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

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


или какой вариант лучше?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-07-31 15:23:46

может есть смысл innoDB использовать с внешними ключами? только елси там есть реально решения... если оно там есть?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Sla
мл. сержант
Сообщения: 73
Зарегистрирован: 2008-08-19 15:09:19

Re: деревовидные связи

Непрочитанное сообщение Sla » 2009-07-31 16:55:58

вот тут есть статейка
http://club.shelek.ru/viewart.php?id=307

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-07-31 17:34:47

я там что-то нифига не опнял, автор не написал цель статьи и какие возможности...

как мне вставить id я не понял, parrent не надо, но а ИД что-ли нету?

как мне переместить раздел к другому родителю? там не увидел чтобы было написано..
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-07-31 17:43:02

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

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

не много старые
http://doc.prototypes.ru/database/neste ... rl/module/
http://webscript.ru/stories/04/09/01/8197045
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-07-31 17:50:39

ну вот ту вот http://habrahabr.ru/blogs/perl/65495/
опять не понтяно
если мак. число ступений будет допустим 10, и много разделов в кажой ступени, НО и если таблица будет больше 2гиг как оно будет?

автор не написал цели, там написано что все родители и подродитеи изменяються может UPDATE будет долго обновлятся если добавлять или переносить раздел?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-08-02 14:21:35

есть таблица:

id
parent_id
active
created


еще тестовая:
id
parent_id
active
created
left_key
right_key
level
tree - # идентификатор дерева если много деревьев (это не надо)


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

вот есть запрос который корректирует дерево внизу, при перемещении:

но как поменять во всем дереве( и во всех подразделах) внизу поле active на 1?

Код: Выделить всё

            my $query = 'UPDATE '.$table_name.
                           ' SET '.$f->{left_key}.' = CASE WHEN '.$f->{right_key}.' <= '.$old->{$f->{right_key}}.'
                                     THEN '.$f->{left_key}.' + '.$skew_edit.'
                                     ELSE CASE WHEN '.$f->{left_key}.' > '.$old->{$f->{right_key}}.'
                                               THEN '.$f->{left_key}.' - '.$skew_tree.'
                                               ELSE '.$f->{left_key}.'
                                          END
                               END,
                    '.$f->{level}.' =  CASE WHEN '.$f->{right_key}.' <= '.$old->{$f->{right_key}}.'
                                    THEN '.$f->{level}.' + '.$skew_level.'
                                    ELSE '.$f->{level}.'
                               END,
                    '.$f->{right_key}.' = CASE WHEN '.$f->{right_key}.' <= '.$old->{$f->{right_key}}.'
                                     THEN '.$f->{right_key}.' + '.$skew_edit.'
                                     ELSE CASE WHEN '.$f->{right_key}.' < '.$new->{$f->{left_key}}.'
                                               THEN '.$f->{right_key}.' - '.$skew_tree.'
                                               ELSE '.$f->{right_key}.'
                                          END
                                END
                WHERE
                    '.($table->{multi} ? $f->{tree}.' = '.$old->{$f->{tree}}.' AND ' : '').
                     $f->{right_key}.' > '.$old->{$f->{left_key}}.' AND '.
                     $f->{left_key}.' < '.$new->{$f->{left_key}}.';';

http://habrahabr.ru/blogs/perl/65495/
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение

Аватара пользователя
ProFTP
подполковник
Сообщения: 3388
Зарегистрирован: 2008-04-13 1:50:04
Откуда: %&й
Контактная информация:

Re: деревовидные связи

Непрочитанное сообщение ProFTP » 2009-10-04 17:27:08

сейчас думаю над архитектурой еще одного дерева...

мне показалось что NestedSet не подойдет для него так как NestedSet все операции кроме SELECT ресурсоемкие!!

недостатки в Nested Set: если вы заметили, точно такая же рекурсия, только там идет UPDATE ресурсоемкий который все дерево изменяет (очень много записей) по этому я нашел решение где-то на opennet.ru на innodb с ускорением за счет внешних ключей и транзакции (чтобы дерево не развалилось во время изменение структуры) говорят что если innodb с большой базой, то грузит сильно сервер, неоднократно сталиквался, но в приципе мне все равно

про мое дерево долго рассказывать:

1)

щас нарисую

"Корень дерева" --> "разедел1"
````````````````` "разедел2"->>>"разедел1"
````````````````` "разедел3"````"разедел2"
````````````````` "разедел4"````"разедел3"->>>>>>"разедел1"
````````````````` "разедел5"````````````````````"разедел2"
````````````````` "разедел6"````````````````````"разедел3"
```````````````````````````````````````````````"разедел4"

из этого:
а) у кадого раздела может быть свой "подраздел(ы)"
б) у кадого раздела может быть "тема(ы) сообщения" как на этом форуме
б2) у темы есть коментарии


думаю все понятно?

2) нужно сделать:
перенос узла,
выборка всех родителей вверх,
просмотр
вывести дерево начиная от како-то элемента,
удаление/изменение атрибутов всего дерева со всеми подчиненными узлами
если ничего не забыл, может еще что-то

все дерево выносить не надо

===
при обычном parent_id:

id
parent_id
(можно еще level)

Преимущества дерева
1) перенос
2) Добавление
3) Нормальный SELECT и SELECT всех родителей (SELECT сразe 50-100 ступеней можно сделать,( т.е. ограничить) а лишние удалить, либо рекурсию) все остальное нормально

Недостатки:
1) удаление всего дерева затруднительно (рекурсию надо делать, или процедуру)
НО в условии, например присутствует, что пользователи не могут когда они захотят все удалить, литит удлаения должен быть (проблем не будет)
2) узменение атрибута узла и всего поддерева (например надо все дерево скрыть начиная с конкретного узла) (рекурсию надо делать, или триггер)

можно записывать level уровень, чтобы сделать еше быстрый SELECT всех родителей и в один НОРМАЛЬНЫЙ запрос


вообщем, как?
писал старался, хотел узнать может есть замечания какие-то?
Pеrl FAQ
perl -e 'print join"",map $$_[rand@$_],([0..9,'a'..'z','A'..'Z'])x30'
ИзображениеИзображение