最近在做项目的时候遇到一个表,将省市区都放到一个表里存储,通过父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也能玩递归的更多相关文章

  1. 你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  2. 【吐血分享】SQL Server With As 递归获取层级关系数据

    纯洁的一周又开始了,今天看到一则新闻,笑尿了,和袁友们一起娱乐下 最近两月在做基于Saas模式的人力资源管理产品,平常数据库设计我经常会遇到如下需求场景: 以前商城类网站在设计类型表的时候,设计成单表 ...

  3. 在论坛中出现的比较难的sql问题:34(递归 获取连续值问题)

    原文:在论坛中出现的比较难的sql问题:34(递归 获取连续值问题) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

  4. 在论坛中出现的比较难的sql问题:33(递归 连续日期问题 )

    原文:在论坛中出现的比较难的sql问题:33(递归 连续日期问题 ) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必 ...

  5. 在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点)

    原文:在论坛中出现的比较难的sql问题:21(递归问题 检索某个节点下所有叶子节点) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. ...

  6. 在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串)

    原文:在论坛中出现的比较难的sql问题:12(递归问题2 拆分字符串) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有 ...

  7. 在论坛中出现的比较难的sql问题:8(递归问题 树形结构分组)

    原文:在论坛中出现的比较难的sql问题:8(递归问题 树形结构分组) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必 ...

  8. sql server 2000/2005递归

    /* 递归查询 塗聚文---SQL Server 2005环境下的实现: */--生成测试数据 create table Dept(ID int,ParentID int,msg varchar(20 ...

  9. 妙用CTE,一条语句实现sql递归查询,SQLServer 递归

    数据库设计中经常碰到父子节点的关系结构,经常需要找到某个节点的根,或者某个节点的所有子节点,一般做法都是在业务层做递归的方式实现,或者数据库存储过程实现.但其实SQLServer提供的CTE可以很好的 ...

随机推荐

  1. log4j的properties详细配置,分级输出日志文件

            log4j是很常用的日志类包,在此做一下配置的记录 加载jar包和properities配置文件             将commons-logging.jar和logging-lo ...

  2. Linux Apache SVN

    yum install mod_dav_svn subversion  httpd mkdir /var/www/svnsvnadmin create /var/www/svn/puppetcd /v ...

  3. Java代码操作HDFS(在/user/root/下面創建目錄)

    1.创建HDFS目录并打成jar包 package Hdfs; import java.io.IOException; import java.net.URI; import org.apache.h ...

  4. HTML+CSS 整站 步骤

    文件夹管理: CSS JS img font html 根据设计图,划分区块 ,即页面布局 重置样式 ;padding:0;} 写main.css  注意:1 距离尽量使用偶数,避免奇数 2 在使用定 ...

  5. Java SE (6)之 多线程

    package com.sunzhiyan03; /* * 演示多线程 * */ public class Demo3 { public Demo3() { // TODO Auto-generate ...

  6. (九)Struts2 防重复提交

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:重复提交示例演示 struts.xml <?xml version ...

  7. OC细节 - 1.深拷贝与浅拷贝详解

    概述 拷贝:复制一个与源对象内容相同的对象 实现拷贝,需要遵守以下两个协议 NSCopying NSMutableCopying 拷贝返回对象的种类 可变,mutableCopy消息返回的对象 不可变 ...

  8. Javascript字符串拼接小技巧

    在Javascript中经常会遇到字符串的问题,但是如果要拼接的字符串过长就比较麻烦了. 如果是在一行的,可读性差不说,如果要换行的,会直接报错. 在此介绍几种Javascript拼接字符串的技巧. ...

  9. 关于Java中的数组转变成字符串问题

    1.用StringBuilder private static String arraytoString(int arr[]){ StringBuilder sb=new StringBuilder( ...

  10. 关于MVC中使用dynamic

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2kAAAB6CAIAAACqQIxZAAAgAElEQVR4nO2dT2wcx53v6zgXAgsYvA