Tree в таблице
От: baboo  
Дата: 16.03.02 12:42
Оценка:
Проблемма — уже голову сломал
Элементы "дерева" хранятся в таблице
У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
Это вообще возможно?
Re: Tree в таблице
От: VVP Россия 67524421
Дата: 16.03.02 13:24
Оценка: 2 (1)
Здравствуйте baboo, Вы писали:

B>Проблемма — уже голову сломал

B>Элементы "дерева" хранятся в таблице
B>У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
B>Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
B>Это вообще возможно?

Сервер какой?
Если Оракл, который поддерживает иерархически запросы, то так:
select WORKTABLE_ID, PARENT_ID, NAME
  from WORKTABLE
  start with PARENT_ID=0
  connect by prior WORKTABLE_ID=PARENT_ID;


Если другой сервер (MSSQL например), то прочитай статью здесь
Автор(ы): Сергей Виноградов
Дата: 16.11.2001
или здесь. Надеюсь, что разберешся.
Никогда не бойся браться делать то, что делать не умеешь. Помни, ковчег был построен любителем. Профессионалы построили Титаник...
Re: Tree в таблице
От: SVM  
Дата: 18.03.02 06:26
Оценка:
Здравствуйте baboo, Вы писали:

B>Проблемма — уже голову сломал

B>Элементы "дерева" хранятся в таблице
B>У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
B>Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
B>Это вообще возможно?

Можно попробовать следующие варианты:
1. Выборка из сохраненной процедуры;
2. Ввести дополнительное поле, по которому
будет производиться сортировка, что-то
вроде PATH VARCHAR (n), содержащее строку
вида "<ORDERNUM_1>/<ORDERNUM_2>/../<ORDERNUM_N",
где <ORDERNUM1_N> — порядковый номер элемента
относительно родителя, заполняется при добавлении
записи.
Ну и выборка будет примерно такая:
SELECT FIELDS FROM TABLE ORDER BY PATH.
Re: Tree в таблице
От: pg Россия  
Дата: 18.03.02 11:09
Оценка:
Здравствуйте baboo, Вы писали:

B>Проблемма — уже голову сломал

B>Элементы "дерева" хранятся в таблице
B>У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
B>Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
B>Это вообще возможно?

Проясни четче, что значит осортированный список.
Например у тебя дерево вида:
1
 11
  113
  114 
 12
2
 21
  212
   213

Как должен выглядеть результат SQL запроса?1,11,113,114,12,2...?
Тут похоже много будет зависеть от SQL сервера. На MSSQL вложенность сохранённых процедур на может быть больше 32. Так что рекурсия не поможет если вложенность не ограничена.
Но... в хелпе по MSSQL2000 есть статья в которой реализован равноширинный обход дерева без рекурсии со вспомогательной таблицей. Как статья называется сейчас не помню. Чего то ...Hierarchical ...
Если интересно то позже напишу что там и как более конкретно.
Глеб
Re: Tree в таблице
От: Merle Австрия http://rsdn.ru
Дата: 18.03.02 12:18
Оценка: 6 (1)
Здравствуйте baboo, Вы писали:

B>Элементы "дерева" хранятся в таблице

B>У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
B>Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
B>Это вообще возможно?
В предложеной структуре одним запросом дерево не вытащишь, если у тебя не Oracle конечно.

Отсюда варианты, либо меняешь структуру таблицы, как в ссылках от VVP.
Либо пользуешь такую процедуру: (для MSSQL, переделать для любого другого диалекта T-SQL думаю проблем не составит)
ID и ID родителя здесь char(20).


CREATE PROCEDURE expand (@current char(20)) as

DECLARE @level int
CREATE TABLE #Result (OrderID IDENTITY(1,1) int,ID char(20),level int)
CREATE TABLE #stack (item char(20), level int)
INSERT INTO #stack VALUES (@current, 1)
SELECT @level = 1

WHILE @level > 0
BEGIN
   IF EXISTS (SELECT 1 FROM #stack WHERE level = @level)
      BEGIN
         SELECT @current = item
         FROM #stack
         WHERE level = @level
         INSERT INTO #Result (ID, level) VALUES (@current, @level)
         DELETE FROM #stack
         WHERE level = @level
            AND item = @current
         INSERT #stack
            SELECT child, @level + 1
            FROM hierarchy
            WHERE parent = @current
         IF @@ROWCOUNT > 0
            SELECT @level = @level + 1
      END
   ELSE
      SELECT @level = @level - 1
END -- WHILE

SELECT #Result.level, hierarhy.* FROM hierarchy INNER JOIN #Result
ON #Result.ID = hierarhy.ID ORDER BY OrderID


The input parameter (@current) indicates the place in the hierarchy to start. It also keeps track of the current item in the main loop.

The local variables used are @level, which keeps track of the current level in the hierarchy.
Мы уже победили, просто это еще не так заметно...
Re: Tree в таблице
От: VVP Россия 67524421
Дата: 19.03.02 13:04
Оценка: 10 (1)
Здравствуйте baboo, Вы писали:

B>Проблемма — уже голову сломал


Я уже отвечал, но хочу описать еще один метод, он не совсем универсален, но часто годится.
Используется в случае маленькой глубины дерева и когда у тебя дерево "статично", то есть не ожидается частого переноса веток.

Помимо ID и PARENT_ID, а можно и вместо них, заводится поле типа VARCHAR(30), хотя размер можно подобрать по вкусу .
Это поле поддерживается триггером на вставку или обновление (как сделать — сущая ерунда, даже объяснять лень).
Формат поля такой (опять же можно придумать свое похожее):

корень ветки: значение поля '001'
элемент принадлежащий корню: '001.001'
и так далее, получаем:
 ID       | PARENT_ID | CONTEXT_ID
----------------------------------------------------------------------
        1 |           | 001
        3 |         1 | 001.001
        4 |         1 | 001.002
        5 |         1 | 001.003
        2 |           | 002
        6 |         2 | 002.001
        9 |         6 | 002.001.001
       10 |         6 | 002.001.002
        7 |         2 | 002.002
        8 |         2 | 002.003

Идея, я думаю, ясна.
Называется такой метод — контекстное дерево. Выборка нужных веток получается селектом с условием LIKE траляля-маляля.

Творческих всем узбеков...
Никогда не бойся браться делать то, что делать не умеешь. Помни, ковчег был построен любителем. Профессионалы построили Титаник...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.