Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности

Новые сообщения [новые:0]
Дайджест
Горячие темы
Избранное [новые:0]
Форумы
Пользователи
Статистика
Статистика нагрузки
Мод. лог
Поиск
|
|
20.12.2001, 14:28
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Есть некоторый иерархический рубрикатор. Сделан стандартно, в одной таблице, следующей структуры ID NAME PARENT_ID LEVEL ORDER PATH 1 'Рубрика 1' NULL 1 1 '0001' 2 'Рубрика 1.1' 1 2 1 '0001 0001' 3 'Рубрика 1.1.1' 2 3 1 '0001 0001 0001' 4 'Рубрика 1.1.2' 2 3 2 '0001 0001 0002' 5 'Рубрика 1.2' 1 2 2 '0001 0002' 6 'Рубрика 1.3' 1 2 3 '0001 0003' ... Поле ORDER - порядок следования элементов с общим родителем в пределах одного уровня. Поле PATH используется для выборки раскрытого дерева одним запросом (сортировка по нему дает упорядоченное дерево, где дети находятся точно под своими родителями, остается только при выводе сдвинуть их вправо на значение поля LEVEL) Теперь же добавилась задача двигать элементы c общим родителем относительно друг друга (вверх-вниз) Чтобы сохранить нормальную функциональность поля PATH, в этом случае после сдвижки нужно производить глобальный апдейт поля PATH для всех детей двух меняющихся местами элементов, что не очень нравится. Есть какие-либо другие решения для организации иерархий с динамическим порядком следования внутри уровня, не требующие подобных телодвижений? Чтобы оставалась возможность выбирать выстроенное дерево одним запросом и не осуществлять множественных апдейтов при изменении положения элементов? Кстати, та же проблема встает и при редактировании иерархии - перемещении одних разделов в другие. Прошу помочь, заранее спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
20.12.2001, 15:02
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Все эти вещи легко решаются, если из перечисленных полей хранить только ID, NAME и PARENT_ID. Остальные поля (LEVEL,ORDER,PATH) должны вычисляться в процедуре вывода (раскрутки) дерева. Если следовать такому принципу, то все изменения структуры дерева делаются с полпинка единичными изменениями поля PARENT_ID. Конечно, выбрать дерево одним запросом не получиться. Зато получиться выбрать дерево одной хранимой процедурой, что не очень сильно отличается от условия "один запрос". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 07:49
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Посмотри статью про иерархию: http://rdbms.narod.ru/article/tree/index.html Вариант со связанной таблицей работает очень быстро, одним запросом, и таблицу не надо всю перестраивать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 09:55
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
To Sergey Vinogradov Я конечно извиняюсь, но при твоем варианте с применением карты дерева в отдельной таблице у меня не получается составить запрос выводящий отсортированное раскрытое дерево. Я был бы тебе очень благодарен, если бы ты привел пример запроса ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 10:41
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
читал когда-то статью в DBMS Magazine в (ох!) 1996 году там как раз знаменитый (хотя у некоторых и вызывающий аллергию Joe Celko расписывал метод представления деревьев с его точки зрения наиболее естественный для SQL http://www.dbmsmag.com/9603d06.html единственный сомнительный момент - поддержка этой структуры требует довольно сложных триггеров. ну и что? простые вещи клепать скушно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 11:04
|
|||
|---|---|---|---|
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Угу, идея хранения деревьев по принципу "вложенных множеств" - красивая... (вот тоже самое по-русски) http://sdm.viptop.ru/articles/sqltrees.html Но она позволяет только легко и просто - развертывать "иерархии" до "10-го колена", или вытаскивать "пути" наверх до "рута" включительно, а вот не менее простую задачу - показать список "детей" одного узла (без "внуков" и "правнуков") - я что-то не смог придумать - как реализовать в такой структуре, так что - старая добрая ссылка на PARENT_ID - тоже себя оправдывает... ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 11:09
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
оп-па. извиняюсь. оказывается на narod.ru лежит как раз оно в переведенном и упрощенном виде и со ссылкой. а отсортированное по заданному полю дерево ИМХО можно сделать только если все тот же PATH делать функцией которая пробегает курсором по SELECT <ваше_поле_сортировки> FROM <ваша_Таблица> Parents Where Child.NodeLeft between Parents.NodeLeft and Parents.NodeRight Order by Parents.NodeLeft чтобы сорт-код был нормальным надо его по вкусу разбавить разделителями и добить с нужной стороны пробелами. Под MS2k это работает нормально. тем у кого функций нет, видимо только процедуры. Счастливые пользователи Sybase SQL Anywhere могут воспользоваться встроенной функцией LIST(...) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 11:24
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
2 qu-qu: Элементарно! Всего-то и нужно сосчитать родителей. Берем NodeLeft и NodeRight родителя и выбираем те записи для которых различие в уровне с родителем ровно 1 --- SELECT C.PK, C.name FROM <Table> C, <Table> P Where (C.nodeleft between @parentNodeLeft and @ParentNodeRight ) and (P.nodeleft between @parentNodeLeft and @ParentNodeRight) and (C.nodeleft between P.nodeleft and P.noderight ) Group BY C.PK, C.name Having Count(P.PK)=2 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
21.12.2001, 12:14
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Мне не очень понятен способ с nodeleft и noderight Я правильно понял, при каждой операции (добавлении очередного узла в любое место) их опять надо пересчитывать? Так это - тот же глобальный апдейт, от которого и хотелось убежать. Я все-таки хотел узнать, нет ли варианта построения иерархии вообще без всяких глобальных апдейтов и рекурсивных движений по дереву. Добавление элемента одиночным инсертом (или двумя в разные таблицы), выборка одним запросом (пусть и сложным) Получается нет способа? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
24.12.2001, 07:04
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
Чтобы сортировать одним запросом, надо использовать рекурсию, либо фунцию написать. Но можно извратиться и без этого. Основная таблица - [T]( [ID], [NAME], [PARENT_ID], [LEVEL], [ORDER] ). Вспомогательная (содержащая всех родителей определенной записи) - [TA]( [ID], [ANCESTOR] ). Запрос: select [NAME] from T as TC order by ( select sum( TT.[ORDER] ) from ( select TP.[ORDER] * power( convert( numeric, 1000 ), 11 - TP.[LEVEL] ) as [ORDER] from TA inner join T as TP on TP.[ID] = TP.[ANCESTOR] where TA.[ID] = TC.[ID] ) as TT ) В таком виде будет работать, если количество уровней < 11, а элементов на уровне < 1000. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
24.12.2001, 07:46
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
> Я все-таки хотел узнать, нет ли варианта построения иерархии вообще без всяких глобальных апдейтов и рекурсивных движений по дереву. Добавление элемента одиночным инсертом (или двумя в разные таблицы), выборка одним запросом (пусть и сложным) Получается нет способа? Вот такая процедура не покажется слишком мудрёной? CREATE PROCEDURE TreeMsg AS declare @level int, @sublevel int set nocount on create table #outres ( Id int identity(1,1) not null Primary Key, MsgId int not null Unique, ParentId int null, LevelNum int not null, OrderByVal varchar(255) null, ) while 1=1 begin set @level=IsNull(@level,0)+1 insert into #outres (MsgId,ParentId,LevelNum) select Id, ParentId, @level from MessageBoard m where (ParentId in (select MsgId from #outres) or ParentId is null) and Id not in (select MsgId from #outres) order by RegDate desc if @@ROWCOUNT=0 break end set @sublevel=1 while @sublevel<=@level begin update self set OrderByVal=IsNull(parent.OrderByVal,'')+right('0000'+convert(varchar(10),self.Id),5)+'.' from #outres self left join #outres parent on self.ParentId=parent.MsgId where self.LevelNum=@sublevel set @sublevel=@sublevel+1 end select o.MsgId, m.Title, m.RegDate, o.ParentId, o.LevelNum from #outres o inner join MessageBoard m on o.MsgId=m.Id order by o.OrderByVal GO Для таблицы CREATE TABLE MessageBoard ( Id int IDENTITY (1, 1) NOT NULL Primary Key, ParentId int NULL , Title varchar(60) NOT NULL , RegDate datetime NOT NULL DEFAULT getdate(), .....) Обращаю ваше внимание, что первый цикл, вычисляющий номер уровня, и второй цикл, вычисляющий поле сортировки вывода дерева, производится столько раз, какая максимальная глубина вложенности дерева +1. Т.е. если максимальный уровень в дереве 10, то цикл выполниться 11 раз, что не есть много. Т.е. элементы здесь не перебираются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|
24.12.2001, 13:09
|
|||
|---|---|---|---|
|
|||
Иерархии с сортировкой внутри уровня. |
|||
|
#18+
С этими деревьями и у меня одна сплошная мука, по тем же причинам. Ну не поддерживаются они напрямую реляционной схемой, и всё тут. Иерархическими - поддерживаются напрямую, а реляционной - нет. С Вашего позволения, некоторые общие мысли. Посмотрим на определения деревьев (не упорядоченных. Модификация для упорядоченных деревьев очевидна). По определению, дерево - это узел ("корень"), который может иметь "потомков" - другие деревья. Т.е. определение в принципе рекурсивное. Чтобы обойти дерево, исходя из этого определения, можно использовать рекурсию. Любая рекурсия может быть приведена к итерации. Тогда дерево - это структура, состоящая из корневого узла, который может быть связан с другими узлами - "потомками".Каждый узел - "потомок" может быть связан со своими узлами - "потомками", причём с любым узлом - "потомком" должен быть связан ровно один узел - предок. Чтобы обойти дерево, исходя из этого определения, можно использовать итерацию. Попробуем по-другому. Дерево из N узлов - это матрица T(NxN), такая что 1) элемент T(i,j) = 1, если узел j является предком узла i; 2) элемент T(i,j) = 0, если узел j НЕ является предком узла i; 3) каждая строка, T(i), кроме одной, должна содержать ровно один единичный элемент 4) должна существовать единственная строка T(k), состоящая из одних нулей, и узел k - это корень дерева. С точки зрения реляционной схемы - ещё хуже, получили таблицу с переменным числом столбцов (или переменное число таблиц), и всё равно, менять нужно много элементов. Да и при выборке итерации нужны. И т.д. Наверное, сколько существует возможных математических аппаратов - столько и определений дерева (можно, например, определить дерево неким формальным языком - и опять, магазинный автомат -> рекурсия). Обратим внимание, что в определениях отсутствует понятие "уровень" или "номер уровня". Реляционная схема не поддерживает рекурсии или итерации иначе, чем через расширения SQL или QBE, или ещё какого-либо реляционного языка (потому что отношение - это НЕупорядоченное множество кортежей атомарных элементов). В случае SQL эти расширения - это язык встроенных процедур/триггеров. Другими словами, SELECT реализует операции над неупорядоченными множествами кортежей, состоящих из некоторых "атомарных" элементов (по определению первой нормальной формы). Это справедливо для любого языка, действующего в рамках реляционной модели. Что же мы должны хранить, явно или неявно, в структуре, моделирующей наше упорядоченное дерево, чтобы можно было сортировать (т.е. "обходить") дерево: 1) Ссылку на предка (явно, или например, "наоборот" - ссылкой на потомка(ов)); 2)Номер потомка (явно или неявно - например, ссылкой на предыдущего брата); 3) И, наконец, информацию, ассоциированную с узлом, из-за которой мы и строим дерево (впрочем, это к делу не относится). Если хотим "просто" делать выборки по уровням: 4) Номер уровня (явно, неявно уже хранится в 1)). Кстати, не видел ещё задачи, где бы потребовалось выбрать не "всех прямых потомков узла Х", а "все узлы 3-го уровня". Видно, что при некоторой произвольной перестройке дерева, необходимо менять всю информацию о положении узла, а поскольку при этом меняется порядок и других узлов (т.е. их "номер при обходе дерева") - и информацию в них тоже. - Если мы хотим делать простые выборки - нужно хранить 1), 2) явно - тогда необходимы сложные обновления. Для справочников, которые редко меняются не так и сложно, как здесь уже упоминалось. IMHO, обсуждаемая здесь идея с "предварительной нумерацией" узлов дерева мне очень понравилась (прочёл в рассылке это сайта №66) - даже завидно, как всё просто. (Ведь почти она же описана у Ахо, Ульмана и Ко в "Структурах данных..." при обсуждении деревьев - а вот не увидел...) А целостность дерева пусть обеспечивает механизм транзакций. - Если нам нужны быстрые обновления - храним 1), 2) неявно (ссылками) - тогда при выборках без процедур не обойтись - нужна рекурсия или итерация. Кстати, ведь в точности та же проблема и при попытке хранить списки. Список ведь тоже структура рекурсивная, и опять, простые обновления - за счёт сложной выборки. И наоборот. Правда, обновлять нужно 2 узла - но ведь не один (вставляемый-удаляемый-перемещаемый)! Ожидать в будущем каких-то расширений SQL (именно SQL! Не языков объектно-ориентированных баз), позволяющих "просто" решить данную задачу, IMHO, не стоит - несоответствие теории даром не проходит. А нам нужен SELECT (или UPDATE), выполняющий операции не над "неупорядоченным множеством кортежей атомарных элементов", а над "множеством упорядоченных кортежей множеств". А вдруг кто-нибудь знает другие красивые идеи по поводу моделирования деревьев в реляционной схеме (возможно, деревьев какого-либо специального вида)? Прошу прощения за очевидные рассуждения - но с деревьями этими и правда проблема. Причём, такое впечатление, что проблема больше концептуальная, и наверняка глубже, чем я представляю. Может, из-за этих проблем и иерархические схемы БД забыты? Хотя в любой предметной области иерархию не встретить - чудо. С уважением - Олег. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
|
|
|

start [/forum/topic.php?fid=46&mobile=1&tid=1824504]: |
0ms |
get settings: |
5ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
43ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
| others: | 219ms |
| total: | 348ms |

| 0 / 0 |
