很多时候,我们做Tree的时候会用到递归。但是一般都是从数据库中拿到数据然后再程序中进行递归。昨天一个巧合,一位同事给我看了数据库中的递归,乍一看还不太明白。

表结构是这样的

CREATE TABLE [dbo].[WA_Menu](
[MenuID] [int] IDENTITY(1,1) NOT NULL,
[MenuName] [nvarchar](20) NULL,
[MenuCode] [nvarchar](32) NULL,
[MenuUrl] [nvarchar](100) NULL,
[MenuIcon] [nvarchar](20) NULL,
[MenuParentID] [int] NULLPRIMARY KEY CLUSTERED
(
[MenuID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

以上隐去了部分字段。

SQL是这样的:

WITH SUB AS(
SELECT * FROM WA_Menu WHERE MenuID = 1
UNION ALL
SELECT A.* FROM WA_MENU A INNER JOIN SUB ON SUB.MenuID = A.MenuParentID
)
SELECT * FROM SUB

是不是比程序中的代码简单,直接返回我要的子集,根据MenuID 得到它所有的子集。

后来百度了一下 WITH AS 的语法(CTE语法),他可以让你定义一段SQL供其他的SQL语句使用。定义部分也是可以的。

如果有多个CTE语句,我们用 分号隔开。如:

WITH A AS
(
-- DO SOMETHING
), B AS
(
-- DO SOMETHING
)
此时,在 A中可以使用A B中可以使用 A B ,最后紧接着的SQL ,一定要使用 CTE引用。

如下面的就不对:
WITH A AS
(
-- DO SOMETHING
), B AS
(
-- DO SOMETHING
)
SELECT * FROM D

因为 D和 A B 子查询没有任何关系,正确的写法应该是:

WITH A AS
(
-- DO SOMETHING
), B AS
(
-- DO SOMETHING
)
SELECT * FROM A INNER JOIN B ON A.ID =B.ID

如果想要递归,只需要在 CTE表达式中union自己的子集,即可。

SQL 中进行递归的更多相关文章

  1. java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误

    后台报出如下错误: Caused by: java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误 ORA-01000: 超出打开游标的最大数 ORA-00 ...

  2. SQL With(递归 CTE 查询)

    本文来自:http://www.cnblogs.com/smailxiaobai/archive/2012/01/16/2323291.html 指定临时命名的结果集,这些结果集称为公用表表达式 (C ...

  3. SQL中常见语句

    SQL中常见语句笔记: --替换字段中的回车符和换行符 ) ), '') --删除表命令 DROP TABLE [dbo].[MGoods_Test] --删除表中数据命令 DELETE FROM [ ...

  4. SQL中Round(),Floor(),Ceiling()函数的浅析

    项目中的一个功能模块上用到了标量值函数,函数中又有ceiling()函数的用法,自己找了一些资料,对SQL中这几个函数做一个简单的记录,方便自己学习.有不足之处欢迎拍砖补充 1.round()函数遵循 ...

  5. 关于sql中in 和 exists 的效率问题,in真的效率低吗

    原文: http://www.cnblogs.com/AdamLee/p/5054674.html 在网上看到很多关于sql中使用in效率低的问题,于是自己做了测试来验证是否是众人说的那样. 群众: ...

  6. 学习sql中的排列组合,在园子里搜着看于是。。。

    学习sql中的排列组合,在园子里搜着看,看到篇文章,于是自己(新手)用了最最原始的sql去写出来: --需求----B, C, F, M and S住在一座房子的不同楼层.--B 不住顶层.C 不住底 ...

  7. SQL中distinct的用法

    SQL中distinct的用法   1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...

  8. hibernate中java类的成员变量类型如何映射到SQL中的数据类型变化

    hibernate映射文件??.hbm.xml配置映射元素详解--Hibernate映射类型 在从Hibernate的java的成员类型映射到SQL中的数据类型,其内映射方式它满足,SQL可以自己调制 ...

  9. C#调用SQL中的存储过程中有output参数,存储过程执行过程中返回信息

      C#调用SQL中的存储过程中有output参数,类型是字符型的时候一定要指定参数的长度.不然获取到的结果总是只有第一字符.本人就是由于这个原因,折腾了很久.在此记录一下,供大家以后参考! 例如: ...

随机推荐

  1. 1076 - Get the Containers

    1076 - Get the Containers    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...

  2. sql注入-整数型

    sql注入整数型   1.按照提示输入1,发现直接给出了SQL语句   2.使用order by判断字段数   首先使用order by 3 ,页面无回显,改为2之后页面显示正确.因此判断当前数据库当 ...

  3. ios离线打包报错Showing Recent Messages :-1: HBuilder has conflicting provisioning settings. HBuilder is automatically signed for development, but a conflicting code signing identity iPhone Distribution has

    1.解决方案找到项目工程文件右击->显示包内容->双击project.pbxproj->搜索distribution改写成Developer

  4. <数据结构>XDOJ.322关键路径长度

    问题与解答 问题描述 计算AOE-网中关键路径的长度. 输入格式 输入数据第一行是一个正整数,表示图中的顶点个数n(顶点将分别按0,1,-,n-1进行编号),顶点数不超过100,其中0为源点,n-1为 ...

  5. Java初学者作业——编写Java程序,简单判断“王者荣耀”英雄收到攻击后是否死亡

    返回本章节 返回作业目录 需求说明: 判断"王者荣耀"中英雄受到攻击后是否死亡? 计算"王者荣耀"中怪物攻击英雄的伤害,做出英雄死亡的判断. 如果英雄受到过量伤 ...

  6. Ranger-Usersync安装

    Ranger-Usersync安装, 配置数据源Unix,Usersync从Unix拉取Users/Groups的数据源, 对应的Ranger版本0.6.0. IP/机器名 安装软件 运行进程 zdh ...

  7. python appium自动化报“Encountered internal error running command: UnknownError: An unknown server-side error occurred while processing the command. Original error: Could not proxy command to remote server

    运行app自动化代码时报"Encountered internal error running command: UnknownError: An unknown server-side e ...

  8. 【Python+Django+Pytest】数据库异常pymysql.err.InterfaceError: (0, '') 解决方案

    问题背景: 接口自动化测试平台,在执行测试案例之外,还需要做以下五件事情(或步骤): 1.查询用户在数据准备中预置的测试套件层数据初始化相关sql  (setUp_class方法中) 2.查询用户在数 ...

  9. js监听网页页面滑动滚动事件,实现导航栏自动显示或隐藏

    /** * 页面滑动滚动事件 * @param e *///0为隐藏,1为显示var s = 1;function scrollFunc(e) { // e存在就用e不存在就用windon.event ...

  10. js字符串首字母大写的不同写法

    写法一: let name = 'hello' name.charAt(0).toUpperCase() + name.slice(1) 写法二: let name = 'hello' name.sl ...