View Full Version : پیمایش درخت ها* مهم
مطهر
چهارشنبه 20 اردیبهشت 1385, 21:41 عصر
با سلام
من این کوئری را نوشتم تا با آن تمام فرزندان یک گره را انتخاب کنم.
دوستان یه زحمتی بکشند تست کنند ببینند درسته با نه.
ممنونم
مطهر
چهارشنبه 20 اردیبهشت 1385, 22:58 عصر
اشتباه نوشته ام. باید صبح تصحیح کنم
AminSobati
چهارشنبه 20 اردیبهشت 1385, 23:42 عصر
اگر از SQL Server 2000 استفاده میکنید، راهش اینه:
USE Northwind
Go
DECLARE @ManagerID int
SET @ManagerID =2
--holds the output treelevel lets us isolate a level in the looped query
DECLARE @outTable table (employeeId int, ManagerID int, treeLevel int, processed bit)
--used to hold the level of the tree we are currently at in the loop
DECLARE @treeLevel as int
SET @treelevel = 1
--get the top level
INSERT into @outTable
SELECT employeeId, ReportsTo, @treelevel as treelevel, 0
FROM dbo.employees as employees
WHERE (employees.ReportsTo = @ManagerID)
WHILE (1 = 1) --imitates do...until construct
BEGIN
INSERT INTO @outTable
SELECT employees.employeeId, employees.ReportsTo,
ht.treelevel + 1 as treelevel,0
FROM dbo.employees as employees
JOIN @outTable as ht
ON employees.ReportsTo = ht.employeeId
--this where isolates a given level of the tree
WHERE ht.processed=0
IF @@rowcount = 0 BREAK
UPDATE @outTable SET processed=1
WHERE treeLevel-1<@treelevel
SET @treelevel = @treelevel + 1
END
--now look at the data in context of the employees we have inserted.
select * from @outTable
و در SQL Server 2005:
USE Northwind
go
DECLARE @ManagerID INT
SET @ManagerID=2;
WITH EmpChart AS
(
SELECT EmployeeId, ReportsTo, 1 AS treelevel
FROM Employees
WHERE (Employees.ReportsTo = @ManagerID)
UNION ALL
SELECT e.EmployeeId, e.ReportsTo, treelevel +1
FROM Employees e
JOIN EmpChart ec
ON e.ReportsTo=ec.EmployeeID
)
SELECT * FROM EmpChart
مطهر
پنج شنبه 21 اردیبهشت 1385, 16:48 عصر
WHILE (1 = 1) --imitates do...until construct
BEGIN
INSERT INTO @outTable
SELECT employees.employeeId, employees.ReportsTo,
ht.treelevel + 1 as treelevel,0
FROM dbo.employees as employees
JOIN @outTable as ht
ON employees.ReportsTo = ht.employeeId
--this where isolates a given level of the tree
WHERE ht.processed=0
IF @@rowcount = 0 BREAK
UPDATE @outTable SET processed=1
WHERE treeLevel-1<@treelevel
SET @treelevel = @treelevel + 1
END
این حلقه یک بار تکرار میشه
یک بار هم قبل در @outTable اصلاعات اومده
سرجمع دو بار-
بدین معنا که دو سطح از فرزندان را برمی داره
اگر تعداد فرزندان نا محدود باشه؟؟؟؟ چی ؟؟؟
AminSobati
پنج شنبه 21 اردیبهشت 1385, 23:55 عصر
این حلقه از شرط 1=1 استفاده میکنه به این مفهوم که انتهایی نداره. اما داخل حلقه کنترل میشه که اگر Query نتیجه ای نداشت، از حلقه خارج بشه. به این شکل تمام فرزندان استخراج خواهند شد(تا هر چند سطح پایینتر).
مطهر
جمعه 22 اردیبهشت 1385, 20:51 عصر
insert into goods(Goods_id,Goods_name,Parent_Id)Values(1,'R1', 0)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(2,'R2', 0)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(3,'N1', 2)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(4,'N2', 2)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(5,'N3', 3)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(6,'N4', 3)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(7,'N5', 5)
insert into goods(Goods_id,Goods_name,Parent_Id)Values(8,'N6', 5)
من کوئری را این جور تغییر دام(قابل فهم برا خودم)
کوئری با آخرین تغییرات
مطمئناً شما همینو کپی می کنید؟
declare @gid smallint
set @gid=2 -- test with 2 , 3. return different result
declare @outtable table(goodsId smallint,
ParentId smallint,
GoodsName nvarchar(15),
treeLevel smallint,
processed bit)
declare @treelevel as smallint
set @treelevel=1
--get top level
insert into @outTable
select goods_id,
Parent_Id,
Goods_name,
@treelevel as treelevel,
0
from dbo.goods as goods
where (goods.parent_id=@gid)
while(1=1)
begin
insert into @outTable
select goods.goods_id,
Goods.Parent_Id,
Goods.Goods_Name,
ht.treelevel+1 as treelevel,
0
from dbo.goods as goods
JOIN @outTable as ht
ON goods.parent_id=ht.goodsid --???
where ht.processed=0
if @@rowcount=0 break
update @outTable set processed=1
where treelevel-1<treelevel
set @treelevel=@treelevel+1
end
select * from @outTable
ممنون از این که وقت می گذارید
AminSobati
جمعه 22 اردیبهشت 1385, 21:50 عصر
شما قسمت WHERE در دستور UPDATE رو به شکل اشتباه تغییر دادین و ضمنا:
SET @treelevel = @treelevel + 1
رو هم حذف کردین!! یعنی باید داشته باشید:
UPDATE @outTable SET processed=1
WHERE treeLevel-1<@treelevel
SET @treelevel = @treelevel + 1
مطهر
جمعه 22 اردیبهشت 1385, 22:22 عصر
با سپاس ار استاد ثباتی
تصحیح کردم. ولی اگر با 2 تست کنیم سطح سوم را برنمی گردنه
AminSobati
جمعه 22 اردیبهشت 1385, 22:29 عصر
من مشکلی نداشتم. مطمئن هستید که Data درست Insert شده؟ این نتیجه Query من با 2 هستش:
3 2 N1 1 1
4 2 N2 1 1
5 3 N3 2 1
6 3 N4 2 1
7 5 N5 3 0
8 5 N6 3 0
همونطور که میبینید TreeLevel تا 3 رفته
مطهر
جمعه 22 اردیبهشت 1385, 22:56 عصر
:گیج::گیج::گیج:
declare @t table(goodsId smallint,
ParentId smallint,
GoodsName nvarchar(50))
declare @id smallint
set @id=2
insert into @t
select goods_id,Parent_id,Goods_Name from goods where parent_id=@id
while(1=1)
begin
insert into @t
select goods_id,Parent_id,Goods_Name from goods
JOIN @t as ht
ON goods.parent_id=ht.goodsid
--where????
if @@rowcount=0 break
--select distinct * from @t
end
select distinct * from @t
من ساده تر نوشتم
فقط یه اشکال داره . حلقه پایان نداره
اگر Break کنیم . داده ها درست استخراج شده اند
مطهر
جمعه 22 اردیبهشت 1385, 23:09 عصر
مطمئن هستید که Data درست Insert شده؟
من کدهای خودم (تاپیک بالاتر)را دوباره کپی کردم.
چه مشکلی می تونه داشته باشه.
با توجه به راهنمایی استاد، کوئری را اصلاح کردم.
تاپیک بالاتر
AminSobati
شنبه 23 اردیبهشت 1385, 17:40 عصر
من مجددا تست کردم، مشکلی ندارم متاسفانه!
declare @gid smallint
set @gid=2
declare @outtable table(goodsId smallint,
ParentId smallint,
GoodsName nvarchar(15),
treeLevel smallint,
processed bit)
declare @treelevel as smallint
set @treelevel=1
--get top level
insert into @outTable
select goods_id,
Parent_Id,
Goods_name,
@treelevel as treelevel,
0
from dbo.goods as goods
where (goods.parent_id=@gid)
while(1=1)
begin
insert into @outTable
select goods.goods_id,
Goods.Parent_Id,
Goods.Goods_Name,
ht.treelevel+1 as treelevel,
0
from dbo.goods as goods
JOIN @outTable as ht
ON goods.parent_id=ht.goodsid
where ht.processed=0
if @@rowcount=0 break
UPDATE @outTable SET processed=1
WHERE treeLevel-1<@treelevel
SET @treelevel = @treelevel + 1
end
select * from @outTable
مطهر
شنبه 23 اردیبهشت 1385, 19:52 عصر
با سپاس و صد سپاس از استاد ارجمند.:قلب::قلب:
مشکل حل شد
حالا به این ترتیب به برگها هم دسترسی دارم.
اونایی که Processed=0
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.