Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Выборка с параметрами из временной таблицы  [new]
FURI-CURI
Member

Откуда: Москва
Сообщений: 5
Есть дерево (по Celko)
Начинаю его обход с помощью курсора, причём обхожу по уровням (0-ой, 1-ый и т.д.). Для каждого уровня я пробегаю по курсору по всем вершинам дерева данного уровня. Так вот, в какой-то момент я определяю, что для текущей вершины обходить её наследников больше не нужно, т.е. поддерево с вершиной в текущей вершине надо исключить из будующих выборок.
Я так полагаю надо использовать временную таблицу из двух полей - left_id и right_id, в которую надо заносить левые и правые стороны вершин, чьи поддеревья надо исключить. Только я не знаю как потом написать выборку, которая смогла бы применить данную таблицу.
Если бы надо было бы исключить id-шники, то, понятное дело, это делалось так:
select * from src_table
where id not in (select id from exclude_table)

Но как подобное сделать не для in, а для between?



Вот, для теста:

--создание
CREATE TABLE [tree] (
	[id] [int] IDENTITY (1, 1) NOT NULL ,
	[data] [varchar] (100) COLLATE Cyrillic_General_CI_AS NOT NULL ,
	[left_id] [int] NULL ,
	[right_id] [int] NULL ,
	CONSTRAINT [PK_tree] PRIMARY KEY  CLUSTERED 
	(
		[id]
	)  ON [PRIMARY] 
) ON [PRIMARY]

INSERT INTO tree (data, left_id, right_id)
VALUES ('A',1,30),
	('B',2,3),
	('C',4,9),
	('D',5,6),
	('E',7,8),
	('F',10,27),
	('G',11,24),
	('H',12,13),
	('I',14,15),
	('J',15,23),
	('K',17,18),
	('L',19,22),
	('M',20,21),
	('O',25,26),
	('P',28,29)

Для просмотра всего дерева:
--declare
declare @data varchar(100)
declare @left_id int
declare @right_id int
declare @level int

--declare cursors
declare c cursor fast_forward
	for
		select t1.data, t1.left_id, t1.right_id, (count(*)-1) as lvl
		from tree as t1, tree as t2
		where
			(t1.left_id between t2.left_id and t2.right_id)
		group by t1.data, t1.left_id, t1.right_id	

--proceed
open c
fetch next from c into @data, @left_id, @right_id, @level


while (@@fetch_status = 0) begin
	print space(@level*2) + @data + '(' + cast(@left_id as varchar(20)) + ',' + cast(@right_id as varchar(20)) + ')'
	
	fetch next from c into @data, @left_id, @right_id, @level
end
	
--end
close c
deallocate c

Сам скрипт:
--declare
declare @data varchar(100)
declare @left_id int
declare @right_id int
declare @level int
declare @cur_level int
declare @exclude_table table (left_id int, right_id int)

set @cur_level = 1

while (1=1) begin
	--declare cursors
	declare c cursor fast_forward
		for
			select t1.data, t1.left_id, t1.right_id, (count(*)-1) as lvl
			from tree as t1, tree as t2
			where
				(t1.left_id between t2.left_id and t2.right_id)
			group by t1.data, t1.left_id, t1.right_id
			having (count(*)-1) = @cur_level
	
	--proceed
	open c
	fetch next from c into @data, @left_id, @right_id, @level

	if (@@fetch_status <> 0)
		break

	--try to exclude subtree F
	if (@data = 'F') begin
		insert into @exclude_table values (@left_id, @right_id)
	end

	while (@@fetch_status = 0) begin
		print space(@level*2) + @data + '(' + cast(@left_id as varchar(20)) + ',' + cast(@right_id as varchar(20)) + ')'
		
		fetch next from c into @data, @left_id, @right_id, @level
	end
	
	--end
	close c
	deallocate c

	set @cur_level = @cur_level + 1
end

close c
deallocate c

________________________________
Мухи дроздофилы - бедные птички...
23 авг 04, 13:12    [900931]     Ответить | Цитировать Сообщить модератору
 Re: Выборка с параметрами из временной таблицы  [new]
FURI-CURI
Member

Откуда: Москва
Сообщений: 5
Неболльшое исправление тестового срипта:

--declare
declare @data varchar(100)
declare @left_id int
declare @right_id int
declare @level int
declare @cur_level int
declare @exclude_table table (left_id int, right_id int)

set @cur_level = 0

while (1=1) begin
	--declare cursors
	declare c cursor fast_forward
		for
			select t1.data, t1.left_id, t1.right_id, (count(*)-1) as lvl
			from tree as t1, tree as t2
			where
				(t1.left_id between t2.left_id and t2.right_id)
				and
				(not exists (select * from @exclude_table where left_id >= t1.left_id and right_id <= t1.right_id))
			group by t1.data, t1.left_id, t1.right_id
			having (count(*)-1) = @cur_level
	
	--proceed
	open c
	fetch next from c into @data, @left_id, @right_id, @level

	if (@@fetch_status <> 0)
		break

	--try to exclude subtree F
	while (@@fetch_status = 0) begin
		if (@data = 'F') begin
			insert into @exclude_table values (@left_id, @right_id)
		end

		print space(@level*2) + @data + '(' + cast(@left_id as varchar(20)) + ',' + cast(@right_id as varchar(20)) + ')'
		
		fetch next from c into @data, @left_id, @right_id, @level
	end
	
	--end
	close c
	deallocate c

	set @cur_level = @cur_level + 1
end

close c
deallocate c

--select * from @exclude_table

Как видно я попытался использовать предикат exists, только всё одно не помогает

________________________________
Мухи дроздофилы - бедные птички...
23 авг 04, 13:30    [901009]     Ответить | Цитировать Сообщить модератору
 Re: Выборка с параметрами из временной таблицы  [new]
FURI-CURI
Member

Откуда: Москва
Сообщений: 5
Ёп...
Надо больше спать :)
Всё, вроде решил.

Кому антиресно, вот:
--declare
declare @data varchar(100)
declare @left_id int
declare @right_id int
declare @level int
declare @cur_level int
declare @exclude_table table (left_id int, right_id int)

set @cur_level = 0

while (1=1) begin
	--declare cursors
	declare c cursor fast_forward
		for
			select t1.data, t1.left_id, t1.right_id, (count(*)-1) as lvl
			from tree as t1, tree as t2
			where
				(t1.left_id between t2.left_id and t2.right_id)
				and
				(not exists (
							select *
							from @exclude_table
							where
									(t1.left_id >= left_id)
									and
									(t1.right_id <= right_id)
							)
				)
			group by t1.data, t1.left_id, t1.right_id
			having (count(*)-1) = @cur_level
	
	--proceed
	open c
	fetch next from c into @data, @left_id, @right_id, @level

	if (@@fetch_status <> 0)
		break

	while (@@fetch_status = 0) begin
		print space(@level*2) + @data + '(' + cast(@left_id as varchar(20)) + ',' + cast(@right_id as varchar(20)) + ')'

		--try to exclude subtree F
		if (@data = 'F') begin
			insert into @exclude_table values (@left_id, @right_id)
		end	
		
		fetch next from c into @data, @left_id, @right_id, @level
	end
	
	--end
	close c
	deallocate c

	set @cur_level = @cur_level + 1
end

close c
deallocate c
________________________________
Мухи дроздофилы - бедные птички...
23 авг 04, 13:45    [901080]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить