![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Подскажите с запросом sql
Vlad Oshin © (2007-12-25 18:04:00)Имеется набор объектов, каждый из которых характеризуется следующим:
1. уникальностью (id )
2. возможностью содержать в себе другие объекты (isfolder. 1-контейнер, 2-просто объект)
3. признаком содержания себя самого в объекте (parentid=id контейнера в котором содержится. Контейнер может быть в контейнере)
Задача - получить все объекты, из указанного контейнера, на всю глубину, т.е. из всех вложенных контейнеров, из вложенных во вложенные и т.д. Только одни объекты(isfolder=2)
ничего умнее не приходит следующего:
select DESCR, ID from SC46 where
(isfolder=2 and parentid=' 1VJ ')
(isfolder=2 and parentid in
(select id from SC46 where isfolder=1 and parentid =' 1VJ '))
(isfolder=2 and parentid in
(select id from SC46 where isfolder=1 and parentid in
(select id from SC46 where isfolder=1 and parentid =' 1VJ ')))
(isfolder=2 and parentid in
(select id from SC46 where isfolder=1 and parentid in
(select id from SC46 where isfolder=1 and parentid in
(select id from SC46 where isfolder=1 and parentid =' 1VJ '))))
....
при очередном запросе даст ноль, значит докопались
Vlad Oshin (2007-12-26 09:45:00) [1]ага..
спасибо
Кщд (2007-12-26 06:09:00) [2]
> Vlad Oshin © (25.12.07 18:04)
если, вдруг, Oracle, то connect by
sniknik (2007-12-25 20:55:00) [3]clickmaker © (25.12.07 18:09) [1]
имхо, с удалениями перебор... т.к. операция "тяжелая".
по идее мой вариант должен быть быстрее (но проверять не буду. нафиг)
DECLARE @ID INT
DECLARE @Lvl INT
DECLARE @Rc INT
SET @ID=1 -- задается с которой записи выборка. сама не выбирается, только "детки"
SET @Lvl=1
DECLARE @Tbl TABLE (ID INT PRIMARY KEY CLUSTERED,PID INT NULL,Lvl INT NOT NULL)
INSERT @tbl (ID,PID,Lvl) SELECT ID,PID,@Lvl FROM MainTable where PID=@ID
SET @Rc=@@RowCount
WHILE @Rc>0 BEGIN
SET @Lvl=@Lvl+1
INSERT @Tbl (ID,PID,Lvl)
SELECT d.ID, d.PID, @Lvl
FROM @Tbl t INNER JOIN MainTable d on t.ID=d.PID
WHERE t.Lvl=@Lvl-1
SET @Rc=@@RowCount
END
SELECT ID FROM @Tbl
в "главной" таблице
ID - это ID
PID - ну это "парент" ID (желательно присутствие индекса по нему)
в выборке
Lvl - это уровень, т.е. если нужны не все а например только третий(или другой) уровень то по нему можно условие в последнем селекте задать.
еще у корневых записей "парент" у меня не null как обычно, а 0, что позволяет не меняя ничего выбирать и из корня (если тут не так, то вариант выборки начиная с "корня" не пройдет).
Ketmar_ (2007-12-25 18:48:00) [4]а говорят «декларативный, декларативный»…
clickmaker (2007-12-25 18:09:00) [5]рекурсия, что-ль?
declare @Current_ID int
declare @TreeLevel int
declare @Stack table (Object_ID int null, TreeLevel int)
declare @Results table (Object_ID int null)
select @Current_ID = @Object_ID
select @TreeLevel = 1
insert into @Stack values (@Current_ID, @TreeLevel)
while @TreeLevel > 0 begin
if exists (select * from @Stack where TreeLevel = @TreeLevel) begin
select top 1 @Current_ID = Object_ID from @Stack where TreeLevel = @TreeLevel
insert into @Results (Object_ID) values (@Current_ID)
delete from @Stack where TreeLevel = @TreeLevel and Object_ID = @Current_ID
if @Type is not null
insert into @Stack
select Object_ID, @TreeLevel + 1
from Objects
where Parent_ID = @Current_ID and Type = @Type
else
insert into @Stack
select Object_ID, @TreeLevel + 1
from Objects
where Parent_ID = @Current_ID
if @@rowcount > 0
select @TreeLevel = @TreeLevel + 1
end
else
select @TreeLevel = @TreeLevel - 1
end
delete from @Results where Object_ID = @Object_ID
select r.Object_ID
from @Results r