ORACLE、SQLSERVER 、MYSQL的递归查询

1.ORACLE 递归查询

递归查询,用于查询当前对象的所有下级对象

例如:

select code from table start with code in
<foreach collection="dto.codes" open="(" separator="," close=")" item="code">
#{code}
</foreach>
connect by prior code=parentCode

2.SQL SERVER 递归查询

正文

SQL SERVER 2005之前的版本只能用函数方法实现,SQL SERVER
2005之后新增了CTE功能,可以利用CTE实现递归查询;

CTE:公用表达式Common Table Expression 是SQL SERVER 2005版本之后引入的一个特性;

填充测试数据

Create table GroupInfo([Id] int,[GroupName] nvarchar(50),[ParentGroupId] int)

Insert GroupInfo

select 0,'某某大学',null union all

select 1,'外语学院',0 union all
select 2,'英语专业',1 union all
select 3,'日语专业',1 union all
select 4,'英语专业一班',2 union all
select 5,'英语专业二班',2 union all
select 6,'日语专业一班',3 union all
select 7,'日语专业二班',3 union all

select 8, '法学院',0 union all
select 9, '刑法学专业',8 union all
select 10,'经济法学专业',8 union all
select 11,'刑法学专业一班',9 union all
select 12,'刑法学专业二班',9 union all
select 13,'经济法学专业一班',10 union all
select 14,'经济法学专业二班',10

效果图

在这里插入图片描述

递归实现Demo

1、根据指定的节点向上获取所有父节点,向下获取所有子节点

–根据指定的节点向下获取所有子节点

with
CTE
as
(
    select * from GroupInfo where Id=1
    union all
    select G.* from CTE inner join GroupInfo as G
    on CTE.Id=G.ParentGroupId
)
select * from CTE order by Id

–根据指定的节点向上获取所有父节点

with
CTE
as
(
    select * from GroupInfo where Id=14
    union all
    select G.* from CTE inner join GroupInfo as G
    on CTE.ParentGroupId=G.Id
)
select * from CTE order by Id
2、构造递归路径

1 --构造递归路径

with
CTE
as
(
    select Id,GroupName,ParentGroupId,GroupPath=CAST( GroupName as nvarchar(max)) from GroupInfo where Id=1
    union all
    select G.*,CAST(CTE.GroupPath+'//'+G.GroupName as nvarchar(max)) as GroupPath from CTE
    inner join GroupInfo as G
    on CTE.Id=G.ParentGroupId
)
select * from CTE

在这里插入图片描述

3、分组递归,将同一条分支上节点放到一起

–通过id字段的字符串的拼接,形成sort字段,再通过sort排序,来实现同一分支上的节点放到一起

WITH
CTE
AS
(
    SELECT * ,CAST(RIGHT('000' + CAST([Id] AS VARCHAR), 3) AS VARCHAR(MAX)) AS sort FROM GroupInfo
    WHERE ParentGroupId = 0
    UNION ALL
    SELECT   GroupInfo.* ,CAST(sort + RIGHT('000' + CAST(GroupInfo.[Id] AS VARCHAR),3) AS VARCHAR(MAX)) AS sort
    FROM CTE
    INNER JOIN GroupInfo ON CTE.Id = GroupInfo.ParentGroupId
)
SELECT * FROM CTE ORDER BY sort

在这里插入图片描述

4、递归层级查询(查询出节点所属的层级)

–查询节点层级

WITH CTE AS (
    SELECT *,1 AS [Level] FROM GroupInfo WHERE ParentGroupId=0
    UNION ALL
    SELECT G.*,CTE.Level+1 FROM GroupInfo as G
    JOIN CTE ON CTE.Id =G.ParentGroupId
)
SELECT * FROM CTE

在这里插入图片描述

3.MYSQL的递归查询

mysql递归查询所有数据的方法:利用【find_in_set()】函数和【group_concat()】函数实现递归查询,代码为【SELECT
queryChildrenAreaInfo(1);】。

find_in_set 函数的语法: FIND_IN_SET(str,strList) str 要查询的字符串 strList 字段名,参数以“,”分隔,如(1,2,6,8) 查询字段(strList)中包含的结果,返回结果null或记录

1、创建表

DROP TABLE IF EXISTS `t_areainfo`;

CREATE TABLE `t_areainfo` (

 `id` int(11) NOT  NULL  AUTO_INCREMENT,

 `level` int(11) DEFAULT '0',

 `name` varchar(255) DEFAULT '0',

 `parentId` int(11) DEFAULT '0',

 `status` int(11) DEFAULT '0',

 PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8;

2、初始数据

INSERT INTO `t_areainfo` VALUES ('1', '0', '中国', '0', '0');
INSERT INTO `t_areainfo` VALUES ('2', '0', '华北区', '1', '0');
INSERT INTO `t_areainfo` VALUES ('3', '0', '华南区', '1', '0');
INSERT INTO `t_areainfo` VALUES ('4', '0', '北京', '2', '0');
INSERT INTO `t_areainfo` VALUES ('5', '0', '海淀区', '4', '0');
INSERT INTO `t_areainfo` VALUES ('6', '0', '丰台区', '4', '0');
INSERT INTO `t_areainfo` VALUES ('7', '0', '朝阳区', '4', '0');
INSERT INTO `t_areainfo` VALUES ('8', '0', '北京XX区1', '4', '0');
INSERT INTO `t_areainfo` VALUES ('9', '0', '北京XX区2', '4', '0');
INSERT INTO `t_areainfo` VALUES ('10', '0', '北京XX区3', '4', '0');
INSERT INTO `t_areainfo` VALUES ('11', '0', '北京XX区4', '4', '0');
INSERT INTO `t_areainfo` VALUES ('12', '0', '北京XX区5', '4', '0');
INSERT INTO `t_areainfo` VALUES ('13', '0', '北京XX区6', '4', '0');
INSERT INTO `t_areainfo` VALUES ('14', '0', '北京XX区7', '4', '0');
INSERT INTO `t_areainfo` VALUES ('15', '0', '北京XX区8', '4', '0');
INSERT INTO `t_areainfo` VALUES ('16', '0', '北京XX区9', '4', '0');
INSERT INTO `t_areainfo` VALUES ('17', '0', '北京XX区10', '4', '0');
INSERT INTO `t_areainfo` VALUES ('18', '0', '北京XX区11', '4', '0');
INSERT INTO `t_areainfo` VALUES ('19', '0', '北京XX区12', '4', '0');
INSERT INTO `t_areainfo` VALUES ('20', '0', '北京XX区13', '4', '0');

3、向下递归

利用find_in_set()函数和group_concat()函数实现递归查询:

DROP FUNCTION IF EXISTS queryChildrenAreaInfo;
DELIMITER ;;
CREATE FUNCTION queryChildrenAreaInfo(areaId INT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);
SET sTemp='$';
SET sTempChd = CAST(areaId AS CHAR);
WHILE sTempChd IS NOT NULL DO
SET sTemp= CONCAT(sTemp,',',sTempChd);
SELECT GROUP_CONCAT(id) INTO sTempChd FROM t_areainfo WHERE FIND_IN_SET(parentId,sTempChd)>0;
END WHILE;
RETURN sTemp;
END
;;
DELIMITER ;

注意:如果创建函数错误,请先执行以下语句:
set global log_bin_trust_function_creators=TRUE;

4、调用方式

SELECT queryChildrenAreaInfo(1);

查询id为"4"下面的所有节点

SELECT * FROM t_areainfo WHERE FIND_IN_SET(id,queryChildrenAreaInfo(4));
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值