权限树取树,设计到一个限制表,求高手解答
本帖最后由 xxyping 于 2012-12-07 09:11:19 编辑 idpid表1
0
010
020
030
010101
010201
020102
030103
030203
0101010101
0201010201
01010101 010101
0302010302
0302020302
iddid表2
101010101
103
10201
表1是一个树表
表2是查找限制表
想要找到所有树下面的最后一层节点
例如:id-0,这样我找到数据应该是01010101\030201\030202\020101
也就是说找的数据是根据表2来限制的,如果表2中有匹配的id为0的,则找到它下面所有的最后一层节点,否则就按照表2中的匹配关系,找到它的子节点下有设置关系的所有最后一层节点
假如id-01,则只能找到01010101;
03的话可以找到030201\030202
求高手给个取树方案,谢谢
[最优解释]
--那你试下这个,bom表太大的话,会比较慢,可以分2次展bom
declare @t1 table(id varchar(10),pid varchar(10))
insert into @t1 values('01','0')
insert into @t1 values('02','0')
insert into @t1 values('03','0')
insert into @t1 values('0101','01')
insert into @t1 values('0102','01')
insert into @t1 values('0201','02')
insert into @t1 values('0301','03')
insert into @t1 values('0302','03')
insert into @t1 values('010101','0101')
insert into @t1 values('020101','0201')
insert into @t1 values('01010101','010101')
insert into @t1 values('030201','0302')
insert into @t1 values('030202','0302')
declare @t2 table(id int, did varchar(10))
insert into @t2 values(1,'01010101')
insert into @t2 values(2,'03')
insert into @t2 values(3,'0201')
declare @id varchar(10)
set @id='0302'
;with cte_bom
as
(
select id,pid ,
rights= case when exists(select 1 from @t2 where did=A.pid )
then 1 else 0 end,
flag = case when pid=@id or id=@id then 1 else 0 end
from @t1 as A where not exists(select 1 from @t1 where id=A.pid)
union all
select A.id,A.pid,
case when cte_bom.rights =1 then 1 else
case when exists(select 1 from @t2 where did=A.pid )
then 1 else 0 end
end,
flag = case when flag=1 then 1 else
case when A.id=@id then 1 else 0 end
end
from cte_bom,@t1 as A
where cte_bom.id = A.pid
)
select id,pid
from cte_bom as A
where not exists(select 1 from @t1 where pid=A.id)
and (rights=1 or exists(select 1 from @t2 where did=A.id ) )
and flag=1
----------------------------
-- Author :TravyLee(物是人非事事休,欲语泪先流!)
-- Date :2012-12-07 09:14:02
-- Version:
-- Microsoft SQL Server 2012 - 11.0.2100.60 (Intel X86)
--Feb 10 2012 19:13:17
--Copyright (c) Microsoft Corporation
--Enterprise Edition: Core-based Licensing on Windows NT 6.1 <X86> (Build 7601: Service Pack 1)
--
----------------------------
--> 测试数据:[a]
if object_id('[a]') is not null
drop table [a]
go
create table [a]
(
[id] varchar(8),
[pid] varchar(6)
)
insert [a]
select '0',null union all
select '01','0' union all
select '02','0' union all
select '03','0' union all
select '0101','01' union all
select '0102','01' union all
select '0201','02' union all
select '0301','03' union all
select '0302','03' union all
select '010101','0101' union all
select '020101','0201' union all
select '01010101','010101' union all
select '030201','0302' union all
select '030202','0302'
--> 测试数据:[b]
if object_id('[b]') is not null
drop table [b]
go
create table [b]
(
[id] int,
[did] varchar(8)
)
insert [b]
select 1,'01010101' union all
select 1,'03' union all
select 1,'0201'
go
DECLARE @id varchar(20)
SET @id = '0'
;WITH
T AS(
-- 定位点成员
select *,levels=0 FROM [a]
WHERE id = @id
UNION ALL
-- 递归成员, 通过引用CTE自身与Dept基表JOIN实现递归
SELECT A.*,B.levels+1
FROM [a] A, T B
WHERE A.[pid] = B.id
)
select
* from t where not exists(select 1 from t a where t.id=a.pid)
/*
idpidlevels
0301032
03020103023
03020203023
02010102013
0102012
010101010101014
*/
--试试看这个是不是要的结果
declare @t1 table(id varchar(10),pid varchar(10))
insert into @t1 values('01','0')
insert into @t1 values('02','0')
insert into @t1 values('03','0')
insert into @t1 values('0101','01')
insert into @t1 values('0102','01')
insert into @t1 values('0201','02')
insert into @t1 values('0301','03')
insert into @t1 values('0302','03')
insert into @t1 values('010101','0101')
insert into @t1 values('020101','0201')
insert into @t1 values('01010101','010101')
insert into @t1 values('030201','0302')
insert into @t1 values('030202','0302')
declare @t2 table(id int, did varchar(10))
insert into @t2 values(1,'01010101')
insert into @t2 values(2,'03')
insert into @t2 values(3,'0201')
declare @id varchar(10)
set @id='0' --要查看的父节点
;with cte_bom
as
(
select id,pid ,flag= case when exists(select 1 from @t2 where did=A.pid )
then 1 else 0 end
from @t1 as A where pid=@id
union all
select A.id,A.pid, case when cte_bom.flag =1 then 1 else
case when exists(select 1 from @t2 where did=A.pid )
then 1 else 0 end
end
from cte_bom,@t1 as A
where cte_bom.id = A.pid
)
select id,pid
from cte_bom as A
where not exists(select 1 from @t1 where pid=A.id)
and (flag=1 or exists(select 1 from @t2 where did=A.id ) )
/*
id pid
-------------------------
030103
0302010302
0302020302
0201010201
01010101010101
*/