SQL也能玩递归
最近在做项目的时候遇到一个表,将省市区都放到一个表里存储,通过父ID字段来表示省市区的关系。
创建表语句
- CREATE TABLE [dbo].[Table_6](
- [id1] [int] NOT NULL,
- [name] [varchar](50) NOT NULL,
- [id2] [int] NOT NULL
- ) ON [PRIMARY]
插入数据
- insert Table_6
- select 1,'江苏',0 union all
- select 2,'南京',1 union all
- select 3,'杭州',4 union all
- select 4,'浙江',0 union all
- select 5,'白下',2 union all
- select 6,'余杭',3
查询结果为
图1
期望的结果
图2
如果该记录的id2能够在表内找到,则将id2对应的记录的名称与当前记录的名称拼接在一起,如果其上层记录的id2不为0,就继续往上找,直到找到其id2为0为止。要找到图1中的父节点很简单,用下面的语句即可。
- select * from [Table_6] A
- inner join [Table_6] B
- on A.id2=B.id1
得到的结果是
图3
这里如果我们仅取图3中的第一列,第五列和最后一列
图4
将图1和图4一起看,会发现现在已经取得了图1中的每个记录的父记录,并且id1都是第一层记录的ID。图4中只有第2和3条记录的id2不为0,也就是说其还有父记录,如果将图4的结果集再和图1关联一次,那么就得到了下面的结果
图5
将图1、图4和图5合并起来看,然后按id1分组,就会发现将每个组中的name拼接起来就是期望的图2的结果了。上述的方法对于有限级有用,但是如果是无限级拼接又该怎么办呢。
在SQL Server 2005中提供了公用表表达式(CTE),这个类似于表变量,但是比表变量效率高,通过它可以实现递归访问表的效果,例如要一次得到图1、图4和图5的结果
- WITH cte AS
- (
- SELECT [level]=1,id1, name, id2 from [Table_6]
- UNION ALL
- SELECT [level]=[level]+1, A.id1, b.name, b.id2
- FROM cte A
- INNER JOIN [Table_6] B
- ON A.id2 = B.id1
- ) select * from cte order by id1
得到的结果是:
最后如果要得到图2的结果,给出完整的SQL语句
- WITH cte AS
- (
- SELECT [level]=1,id1, name, id2 from [Table_6]
- UNION ALL
- SELECT [level]=[level]+1, A.id1, b.name, b.id2
- FROM cte A
- INNER JOIN [Table_6] B
- ON A.id2 = B.id1
- )
- SELECT A.id1, name = STUFF((SELECT '-'+name FROM cte B
- WHERE b.id1=a.id1 ORDER BY [level] DESC FOR XML PATH('')),1,1,''), id2 = MAX(CASE WHEN [level]=1 THEN id2 END)
- FROM cte A GROUP BY id1
SQL也能玩递归的更多相关文章
- 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 【吐血分享】SQL Server With As 递归获取层级关系数据
纯洁的一周又开始了,今天看到一则新闻,笑尿了,和袁友们一起娱乐下 最近两月在做基于Saas模式的人力资源管理产品,平常数据库设计我经常会遇到如下需求场景: 以前商城类网站在设计类型表的时候,设计成单表 ...
- 在论坛中出现的比较难的sql问题:34(递归 获取连续值问题)
原文:在论坛中出现的比较难的sql问题:34(递归 获取连续值问题) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.
- 在论坛中出现的比较难的sql问题:33(递归 连续日期问题 )
原文:在论坛中出现的比较难的sql问题:33(递归 连续日期问题 ) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必 ...
- 在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点)
原文:在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. ...
- 在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串)
原文:在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有 ...
- 在论坛中出现的比较难的sql问题:8(递归问题 树形结构分组)
原文:在论坛中出现的比较难的sql问题:8(递归问题 树形结构分组) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必 ...
- sql server 2000/2005递归
/* 递归查询 塗聚文---SQL Server 2005环境下的实现: */--生成测试数据 create table Dept(ID int,ParentID int,msg varchar(20 ...
- 妙用CTE,一条语句实现sql递归查询,SQLServer 递归
数据库设计中经常碰到父子节点的关系结构,经常需要找到某个节点的根,或者某个节点的所有子节点,一般做法都是在业务层做递归的方式实现,或者数据库存储过程实现.但其实SQLServer提供的CTE可以很好的 ...
随机推荐
- Oracle创建存储过程、执行存储过程基本语法
>>>>>>>>>>>>>>>>>>>>>>>>> ...
- Big Data應用:以"玩家意見"之數據分析來探討何謂"健康型線上遊戲"(上)
首先,所有資料都可以從網路上找到,只是我做了一些分析與整理而已.純粹分享心得~~ 最近再做研究的時候我跟我的同事K先生在某次偶然的討論中發現了一件有趣的事情. [疑~~~~~~~新楓之谷的玩家人氣指數 ...
- C#语法糖之第二篇: 参数默认值和命名参数 对象初始化器与集合初始化器
今天继续写上一篇文章C#4.0语法糖之第二篇,在开始今天的文章之前感谢各位园友的支持,通过昨天写的文章,今天有很多园友们也提出了文章中的一些不足,再次感谢这些关心我的园友,在以后些文章的过程中不断的完 ...
- 自己写的SqlHelper
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using ...
- 前端开发bower包管理器
Bower 是 twitter 推出的一款包管理工具,基于nodejs的模块化思想,他可以很好的帮助你帮你解决js的依赖管理,比如jquery angular bootstrap 等等. 可以很方便的 ...
- Java 设计模式_复合模式(2016-08-31)
一.什么是复合模式? 在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义: 将多个模式结合起来形成一个“框架”,以解决一般性问题 一提到“框架”,可能最容易联想到的 ...
- 【转】NHibernate入门教程
开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo 摘要: 热衷于开源框架探索的我发现A ...
- nullptr和NULL 区别
注:本文内容摘自网络,准确性有待验证,现阶段仅供学习参考.尊重作品作者成果,原文链接 :http://www.2cto.com/kf/201302/190008.html 1.为什要有nullptr ...
- Problem 1010 - 素数环问题
#include<iostream> #include<string> #include<algorithm> #include<vector> #in ...
- hibernate一些方法
session.flush() 同步缓存与数据库数据 session.evict(obj) 关闭指定对象缓存 session.clear() 关闭所有缓存 iterator(会把数据放入缓存) 下次 ...