Проблемма — уже голову сломал
Элементы "дерева" хранятся в таблице
У каждой записи есть ИД и ИД родителя, записи "перемешаны", вложенность не ограничена.
Требуется вывести SQL запросом отсортированный список(где записи в том же порядке, что и в дереве).
Это вообще возможно?
Здравствуйте 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 например), то прочитай статью здесь
Здравствуйте 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.
Здравствуйте 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 ...
Если интересно то позже напишу что там и как более конкретно.
Здравствуйте 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-- WHILESELECT #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.
Здравствуйте baboo, Вы писали:
B>Проблемма — уже голову сломал
Я уже отвечал, но хочу описать еще один метод, он не совсем универсален, но часто годится.
Используется в случае маленькой глубины дерева и когда у тебя дерево "статично", то есть не ожидается частого переноса веток.
Помимо ID и PARENT_ID, а можно и вместо них, заводится поле типа VARCHAR(30), хотя размер можно подобрать по вкусу .
Это поле поддерживается триггером на вставку или обновление (как сделать — сущая ерунда, даже объяснять лень).
Формат поля такой (опять же можно придумать свое похожее):
корень ветки: значение поля '001'
элемент принадлежащий корню: '001.001'
и так далее, получаем: