您的位置:首页 > 数据库

SQL 语句技巧--递归查询机构和下属机构的用户数

2008-08-26 11:38 796 查看
今天,一个同事说有个查询比较复杂,需求是:查询机构下的用户数(包括下面全部机构用户),同时还要统计下属机构的用户数。

业务要求:要统计总公司下的用户,还要统计总公司下属的全部机构(技术部,分公司等)的用户数,

同时还要统计技术部,这时统计技术部的用户,还可能包含技术一部,技术二部,技术三部,可能技术一部下面还包含测试部等等部门的用户

依此类推,统计下面的技术一部,和技术一部下面的测试部

同事说这样的话要在程序里递归查询全部机构,就可以得到结果,要写很多条sql语句,能不能用一条sql查询出来。

后来自己试着用一个SQL语句统计出各个机构(包含下属机构)的用户数据,在SQL server 2005里有CTE实现递归查询。但只能查询一级的数据,如查询总公司的可以,但下面个部门,各个子公司就不好查询了总数了。而且在一条sql语句实现递归不太可能,这时考虑一下,发现用表值函数来实现,结合Cross apply来查询其下属机构的用户数。以下是实现T_SQL代码:

表值函数:

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

-- =============================================

-- Author: 郑平

-- Create date: 2008年8月26日11:14:15

-- Description: 返回机构下面的全部机构(包含本机构)

-- =============================================

CREATE FUNCTION subOrgs

(

@orgid varchar(32)

)

RETURNS @tab table(id varchar(32))

AS

BEGIN

;

with org(orgid)

as

(

select a.oid from orgunitlink a

where a.pid=@orgid

union all

select c.oid

from orgunitlink c inner join org aa

on aa.orgid=c.pid

)

insert into @tab select orgid from org union select @orgid

RETURN

END

GO

--查询sql

select t.objname,sum(y.num) num,t.id from

(select b.objname,count(*) num,b.id from humres a inner join

orgunit b on a.orgid=b.id

inner join orgunitlink c on c.oid=b.id where a.isdelete=0 and

a.workstatus<>'402881ea0b1c751a010b1cd2ae770008'

group by b.objname,b.id,c.pid)t

CROSS APPLY subOrgs(id) f

inner join

(select b.objname,count(*) num,b.id from humres a inner join

orgunit b on a.orgid=b.id

inner join orgunitlink c on c.oid=b.id where a.isdelete=0 and

a.workstatus<>'402881ea0b1c751a010b1cd2ae770008'

group by b.objname,b.id,c.pid)

y on y.id=f.id group by t.objname,t.id order by 2 desc

以上查询的速度很快,而且不使用递归查询数据库,是一个比较好的解决办法,下面是查询结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: