日期:2014-05-18  浏览次数:20593 次

急求一条查询SQL语句---父类和子类关系的
现有一个类别表A包含栏位如下:
ClassID,ClassName, Validate, ParentClassID

如果记录里的SELECT * FROM A WHERE ClassID=@ClassID AND ISNULL(ParentClassID,'')='' 有值表示该ClassID为最外层的父类别
如果SELECT * FROM A WHERE ParentClassID=@ClassID 没有查询到结果表示该ClassID 为最底层的子类别。

现求一SQL实现下述功能:
  对于一个ClassID,它既不是最外层的父类别,也不是最底层的子类别,要求查询出该ClassID下的所有最底层的子类别
  比如说类别001 的父类别是000,它下面有类别002,003,004,005,;004下面又有006,007。007下面又有008
  那么我要得到的001下面的所有最底层子类别应该为002,003,005,006,008

求高手指点呀,尽量不要使用游标。



------解决方案--------------------
SQL code


--参考查询指定父节点下的所有子节点:
USE tempdb
GO

-- 建立演示环境
CREATE TABLE Dept(
 id int PRIMARY KEY, 
 parent_id int,
 name nvarchar(20))
INSERT Dept
SELECT 0, 0, N'<全部>' UNION ALL
SELECT 1, 0, N'财务部' UNION ALL
SELECT 2, 0, N'行政部' UNION ALL
SELECT 3, 0, N'业务部' UNION ALL
SELECT 4, 0, N'业务部' UNION ALL
SELECT 5, 4, N'销售部' UNION ALL
SELECT 6, 4, N'MIS' UNION ALL
SELECT 7, 6, N'UI' UNION ALL
SELECT 8, 6, N'软件开发' UNION ALL
SELECT 9, 8, N'内部开发'
GO

-- 查询指定部门下面的所有部门
DECLARE @Dept_name nvarchar(20)
SET @Dept_name = N'MIS'
;WITH
DEPTS AS(
 -- 定位点成员
 SELECT * FROM Dept
 WHERE name = @Dept_name
 UNION ALL
 -- 递归成员, 通过引用CTE自身与Dept基表JOIN实现递归
 SELECT A.*
 FROM Dept A, DEPTS B
 WHERE A.parent_id = B.id
)
SELECT * FROM DEPTS
GO

-- 删除演示环境
DROP TABLE Dept

----CTE的综合应用

USE tempdb
GO

-- 建立演示环境
CREATE TABLE Dept(
 id int PRIMARY KEY, 
 parent_id int,
 name nvarchar(20))
INSERT Dept
SELECT 0, 0, N'<全部>' UNION ALL
SELECT 1, 0, N'财务部' UNION ALL
SELECT 2, 0, N'行政部' UNION ALL
SELECT 3, 0, N'业务部' UNION ALL
SELECT 4, 0, N'业务部' UNION ALL
SELECT 5, 4, N'销售部' UNION ALL
SELECT 6, 4, N'MIS' UNION ALL
SELECT 7, 6, N'UI' UNION ALL
SELECT 8, 6, N'软件开发' UNION ALL
SELECT 9, 8, N'内部开发'
GO

-- 查询指定部门下面的所有部门, 并汇总各部门的下级部门数
DECLARE @Dept_name nvarchar(20)
SET @Dept_name = N'MIS'
;WITH
DEPTS AS(   -- 查询指定部门及其下的所有子部门
 -- 定位点成员
 SELECT * FROM Dept
 WHERE name = @Dept_name
 UNION ALL
 -- 递归成员, 通过引用CTE自身与Dept基表JOIN实现递归
 SELECT A.*
 FROM Dept A, DEPTS B
 WHERE A.parent_id = B.id
),
DEPTCHILD AS(  -- 引用第1个CTE,查询其每条记录对应的部门下的所有子部门
 SELECT 
  Dept_id = P.id, C.id, C.parent_id
 FROM DEPTS P, Dept C
 WHERE P.id = C.parent_id
 UNION ALL
 SELECT 
  P.Dept_id, C.id, C.parent_id
 FROM DEPTCHILD P, Dept C
 WHERE P.id = C.parent_id
),
DEPTCHILDCNT AS( -- 引用第2个CTE, 汇总得到各部门下的子部门数
 SELECT 
  Dept_id, Cnt = COUNT(*)
 FROM DEPTCHILD
 GROUP BY Dept_id
)
SELECT    -- JOIN第1,3个CTE,得到最终的查询结果
 D.*,
 ChildDeptCount = ISNULL(DS.Cnt, 0)
FROM DEPTS D
 LEFT JOIN DEPTCHILDCNT DS
  ON D.id = DS.Dept_id
GO

-- 删除演示环境
DROP TABLE Dept

------解决方案--------------------
SQL code

if OBJECT_ID('tempdb..#t_class') is not null
drop table #t_class

create table #t_class(cid int, cname varchar(10), p_cid int)

insert into #t_class
select 1, 'Class1', null union all
select 2, 'Class2', 1 union all
select 3, 'Class3', 1 union all
select 4, 'Class4', 2 union all
select 5, 'Class5', 2 union all
select 6, 'Class6', 3 union all
select 7, 'Class7', 3 union all
select 8, 'Class8', 5 
;
With cte as
(
 select cid,cname,p_cid,0 lvl, cast('/'+cname as nvarchar) pth from #t_class
 where p_cid is null
 union all
 select e.cid,e.cname,e.p_cid,c.lvl+1, cast(c.pth + '/' + e.cname as nvarchar) pth from cte c
 inner join #t_class e
 on c.cid = e.p_cid
)
select * from cte
where pth like '%Class2%' --找出class2下的班级

------解决方案--------------------
探讨

引用:
SQL code



--参考查询指定父节点下的所有子节点:
USE tempdb
GO

-- 建立演示环境
CREATE TABLE Dept(
id int PRIMARY KEY,
parent_id int,
name nvarchar(20))
INSERT Dept
SELECT 0, 0, N'<全部>' UNION AL……

------解决方案--------------------
SQL code

/*
标题:获取某个节点所有的最底层节点
作者:爱新觉罗·毓华(十八年风雨,守得冰