MSSQL 基础之无限父子级数据拉平

浏览: 3195

引言

今天学员群有位亲遇到这样一个问题:父子级省市数据希望能够拉平成省、市、县、镇。父子级这种问题,解决之道通常就是递归。之前可能需要游标或者嵌套循环来解决,现在MSSQL提供了CTE这个强大的东东,支持递归查询。万民之福啊!!!

知识点

公用表表达式(Common Table Expression) CTE:是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中被多次引用。使用公用表达式可以让语句更加清晰简练.

递归公用表表达式很像派生表(Derived Tables ),指的是在CTE内的语句中调用其自身的CTE.与派生表不同的是,CTE可以在一次定义多次进行派生递归.对于递归的概念,是指一个函数或是过程直接或者间接的调用其自身。

案例

step1、测试数据(群友友情赞助,赞个。在这儿也提下,提问SQL这种问题的时候最好都提供下示例数据,要不自己造只想吐槽)

create table tb(id varchar(3) , pid varchar(3) , name varchar(10));  
insert into tb values('001' , null , '广东省');
insert into tb values('002' , '001' , '广州市');
insert into tb values('003' , '001' , '深圳市') ;
insert into tb values('004' , '002' , '天河区') ;
insert into tb values('005' , '003' , '罗湖区');
insert into tb values('006' , '003' , '福田区') ;
insert into tb values('007' , '003' , '宝安区') ;
insert into tb values('008' , '007' , '西乡镇') ;
insert into tb values('009' , '007' , '龙华镇');
insert into tb values('010' , '007' , '松岗镇');

step2、解决方案

with tmp
as
(
select id,pid,name,1 tlevel,cast(id as varchar(4000)) as tcode from tb where tb.pid is null
union all
select tb.id,tb.pid,tb.name,tlevel+1,cast(tmp.tcode+tb.id as varchar(4000)) from tb
join tmp on tb.pid = tmp.id
)
,tmp1
as
(
select *
from tmp where id not in(
select pid from tmp where pid is not null
)
)
select max(case when tmp.tlevel = 1 then tmp.name end) 省,
max(case when tmp.tlevel = 2 then tmp.name end) 市,
max(case when tmp.tlevel = 3 then tmp.name end) 县,
max(case when tmp1.tlevel = 4 then tmp1.name else null end) 镇
from tmp1
left join tmp on tmp1.tcode like tmp.tcode+'%'
group by tmp1.tcode

step3、效果展示


其中的概念和思路可以参考下面的博客。

参考链接:http://www.cnblogs.com/zjflove/p/4245990.html

扩展

题目中提到了无限级这个高大上的词,实际案例中却是限定级的,楼主这个标题党。各位亲是不是已经在心里无数次的问候过我了。莫急,我觉得按上面的思路实现无限级仅是时间问题。各位可以顺着这个思路尝试下……

推荐 3
本文由 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

7 个评论

不懂CTE是啥 是不是和Pivot一个意思。。
悟

回复 老头子

不是,CTE是临时表的概念,Pivot是透视能够行列转置。
老头子

老头子 回复

with as的高大上写法
哪有无限级哦,CTE with as 默认有递归级别的,而且也可以手动设置递归级别
悟

回复 郑大鹏

无限级是个说法,谁也不会设计100+级吧
今天在实际项目中使用了博主的递归处理方法,效果很不错。有个小问题就是执行效率,项目中的组织机构数据大概2W行,数据库完全执行时间在20分钟左右,请问这个逻辑是否还有优化的空间?
对我有用,感谢。

要回复文章请先登录注册