PDA

View Full Version : Truy vấn theo kiểu đệ quy???



PTBT
24-08-2004, 02:11
Mình có một table GrantAuthority(TaskID,EmpGrantID,EmGrantedID)
ví dụ dữ liệu thế này:
TaskID EmpGrantID EmpGrantedID
X A B
X B C
X C D
.....
Viết câu sql thế nào để khi D login vào mình biết đựơc người ủy quyền gốc là A?

bete
24-08-2004, 04:06
Thân gửi PTBT: như vầy có được không:

các giá trị xuất hiện ở cột EmpGrantID nhưng không xuất hiện ở cột EmpGrantedID
(có lẽ cần thêm điều kiện là 2 TaskID phải giống nhau)

???

-thân

PTBT
24-08-2004, 05:07
Đúng rồi đó bạn cùng TaskID.

oj_n
24-08-2004, 16:46
It's a hierarchy problem. Here is a solution. Adapt to your need.

create table tmp (TaskID char,EmpGrantID char, EmpGrantedID char)
insert tmp select 'X', 'A', 'B'
union all select 'X', 'B', 'C'
union all select 'X', 'C', 'D'
union all select 'X', 'B', 'E'

go
create function dbo.findParent(@EmpGrantedID char,@TaskID char)
returns char
as
begin
declare @tb table (pkid int identity primary key,EmpGrantID char, EmpGrantedID char)
declare @EmpGrantID char

while 1=1
begin
select @EmpGrantID=EmpGrantID
from tmp
where EmpGrantedID=@EmpGrantedID
and TaskID=@TaskID
if @@rowcount=0 break
insert @tb values(@EmpGrantID,@EmpGrantedID)
set @EmpGrantedID=@EmpGrantID
end
return (select top 1 EmpGrantID from @tb order by pkid desc)
end
go
select dbo.findParent('D','X') as EmpGrantID

bete
24-08-2004, 19:56
Thân gửi oj_n: nếu chỉ cần tìm người ủy quyền gốc cho từng taskID thì có thể xài chỉ 1 câu truy vấn (query):

select ...... minus (hoặc except hoặc not exists) .....

(xuất hiện ở cột EmpGrantID nhưng không xuất hiện ở cột EmpGrantedID và 2 TaskID giống nhau)

có được không ????

(có gì sai sót mong các bạn chỉ giúp, xin cám ơn)

-thân

PTBT
24-08-2004, 23:40
Cảm ơn các bạn đã góp ý, cách của oj_n mình sẽ xem kỹ lại, còn cách của bete sẽ ko giải quyết được nếu:
X A B
X C B
mình sẽ ko biết ủy quyền gốc của B là ai?

sontinh2004
25-08-2004, 02:19
You can also try the following ... Note how @rVar is used in the recursive loop.
-------------------------------------------
alter procedure FindRoot
( @pTaskId varchar(50), @pVar varchar(50))
as

declare @rVar varchar(50) --recursive var
declare @bFound int --0: not found, 1: found

set @rVar = @pVar
set @bFound = 0
while exists(select 1 from GrantAuthority where taskid = @pTaskId and EmpGrantedId = @rVar)
select @rVar = EmpGrantId, @bFound = 1 from GrantAuthority
where taskid = @pTaskId and EmpGrantedId = @rVar

if @bFound = 1 select @rVar as ReturnVal
else select 'Not found'
------------------------------------------
Run the following test cases:
FindRoot 'x', 'a'
FindRoot 'x', 'b'
FindRoot 'x', 'c'
FindRoot 'x', 'd'

It should give u what you need.
-----
Gosh, I'm missing all the nice things with SQL Server. I'm doing Oracle now ... :(. Good l uck

bete
25-08-2004, 02:26
Thân gửi PTBT: mình có thể có cả hai dòng

X A B
X C B

trong CSDL cùng 1 lúc ???

Lúc đó mình sẽ in ra cái nào: A hay C ???

-thân

oj_n
02-09-2004, 16:39
I like SonTinh's exist(). It should make the UDF a bit cleaner.

As for bete/ptbt, I would suggest you take a look at this article written by a colleague MVP: http://www.sqlmag.com/Articles/Index.cfm?ArticleID=8826