当前位置:首页 » 编程语言 » sql语句递归

sql语句递归

发布时间: 2024-06-23 21:40:29

sql 函数递归

给你一个例子,跟这个差不多:
CREATE TABLE T(ID INT ,PID INT)
INSERT INTO T SELECT 1,0
UNION ALL SELECT 2,0
UNION ALL SELECT 3,1
UNION ALL SELECT 4,1
UNION ALL SELECT 5,2
UNION ALL SELECT 6,4
UNION ALL SELECT 7,3
UNION ALL SELECT 8,4
GO
--测试数据

CREATE FUNCTION F(@ID INT)
RETURNS VARCHAR(20)
AS
BEGIN
DECLARE @R VARCHAR(20)
SET @R=@ID
WHILE ISNULL(@ID,'')<>''
BEGIN
SELECT @R=CAST(PID AS VARCHAR(20))+'.'+@R FROM T WHERE ID=@ID
SELECT @ID=PID FROM T WHERE ID=@ID
END
RETURN @R
END
GO
--生成目录

CREATE FUNCTION F2(@F VARCHAR(20))
RETURNS VARCHAR(20)
BEGIN
DECLARE @R VARCHAR(20)
SET @R=''
SET @F=SUBSTRING(@F,4,LEN(@F))
WHILE CHARINDEX('.',@F,1)<>0
BEGIN
SET @F=SUBSTRING(@F,CHARINDEX('.',@F,1)+1,LEN(@F))
SET @R='-'+@R
END
RETURN @R
END
GO
--生成前缀符号

SELECT DBO.F2(DBO.F(ID))+CAST(ID AS VARCHAR) FROM T ORDER BY DBO.F(ID)
GO

--结果

DROP TABLE T
DROP FUNCTION F
DROP FUNCTION F2

----------------------------------------------------以下为结果集--------------------------------------------------------------

1
-3
--7
-4
--6
--8
2
-5

② 如何用一段SQL语句递归找到一个目录下的所有子目录

有一个存储目录树的表,定义目录间的关系字段有两个:
如下:(ClassID表示该目录的编号,ClassParentID表示它的父目录的编号)

ClassID ClassParentID
1 1
2 1
3 2
4 3
5 3

表示的关系应该是

-1--(根目录)
|
-2--(第二级目录)
|
-3--(第三级目录)
|
-4--(第四级目录)
|
-5--(第四级目录)

这样的目录关系.

那么我通过知道一个目录的ClassID,如何通过一条SQL语句找到所有该目录的子目录?

如:

"SELECT * FROM 表 WHERE ClassParentID = "+ClassID+"and ClassParentID <>"+ClassID

但只能找到第一层的子目录,如何找到所有子目录,请大家给一条SQL语句实现!!

(因为事先不知道目录有多少层,当然一定是一条带有while循环的SQL语句)

1、

create table Test2
(
ClassID int,
ClassParentID int,
)
go

create proc Test2_proc
@nClassParentID int -- 要查询的父节点ID 号
as
begin
set nocount on
--
declare @nClassID int,
@nIndex int
-- create TempTable
create table #ClassIDTemp
(
nIndex int identity(1,1),
ClassID int,
ClassParentID int,
nFlag int default(0),
)
create index #ClassIDTemp_Index on #ClassIDTemp(nIndex)

-- insert First RecordSet

insert into #ClassIDTemp(ClassID,ClassParentID) select
ClassID,ClassParentID from Test2 where ClassParentID =
@nClassParentID order by ClassParentID
-- Circle
while(0=0)
begin

select top 1 @nIndex = nIndex, @nClassID = ClassID
from #ClassIDTemp where nFlag = 0 order by nIndex
asc
if @@rowcount = 0
break
else
begin

insert into #ClassIDTemp(ClassID,ClassParentID) select
ClassID,ClassParentID from Test2 where ClassParentID =
@nClassID order by ClassParentID
end
update #ClassIDTemp set nFlag = 1 where nIndex = @nIndex
end

-- Select Result
select ClassID,ClassParentID from #ClassIDTemp order by nIndex
if exists(select * from sysobjects where name = '#ClassIDTemp')
drop table #ClassIDTemp
end
go

2、

declare @Table table ( ClassID int primary key , ClassParentID int)
declare @Test table ( ClassID int primary key , ClassParentID int)

insert into @Table values ( 1, 0 ) -- 建议这里是 1,0 而不是 1, 1
insert into @Table values ( 2, 1 )
insert into @Table values ( 3, 2 )
insert into @Table values ( 4, 3 )
insert into @Table values ( 5, 3 )

insert into @Test select * from @Table where ClassID = 2

while exists ( select * from @Table A
inner join @Test B
on A.ClassParentID = B.ClassID
where A.ClassID not in ( select ClassID from @Test ) )
begin
insert into @Test
select A.* from @Table A
inner join @Test B
on A.ClassParentID = B.ClassID
where A.ClassID not in ( select ClassID from @Test )
end

select * from @Test

3、

sql1 = "(SELECT ClassID FROM 表 WHERE ClassParentID =" + 变量 + ")"

sql2 = "(SELECT ClassID FROM 表 WHERE (ClassParentID IN
"+ sql1 + ") OR (ClassID IN " + sql1 + "))"

sql = "SELECT * FROM 表 WHERE ClassParentID IN " + sql2 + " OR ClassID IN " + sql2

这个办法可实现1到4级的所有情况(包括只有2级、3级的情况)

4、--我的方法是用自定义函数实现,这样具有通用性

--测试

--测试数据
create table 表(ClassID int,ClassParentID int)
insert 表 select 1,0
union all select 2,1
union all select 3,2
union all select 4,3
union all select 5,3
go

--自定义函数,返回指定目录下的所有子目录列表
create function f_child(@ClassID int)
returns @re table(ClassID int,Level int)
as
begin
declare @l int
set @l=0
insert @re select @ClassID,@l
while @@rowcount>0 --直接用@@rowcount判断
begin
set @l=@l+1
insert @re select a.ClassID,@l
from 表 a join @re b on a.ClassParentID=b.ClassID
where b.level=@l-1
end
return
end
go

--调用函数实现查询
select a.* from 表 a join dbo.f_child(1) b on a.ClassID=b.ClassID
go

--加上缩进效果
select ClassID=space(b.level*4)+cast(a.ClassID as varchar),a.ClassParentID
from 表 a join dbo.f_child(1) b on a.ClassID=b.ClassID

go
--删除测试环境
drop table 表
drop function f_child

/*--测试结果
ClassID ClassParentID
----------- -------------
1 0
2 1
3 2
4 3
5 3

(所影响的行数为 5 行)

ClassID ClassParentID
-------------- ----------------
10
2 1
3 2
4 3
5 3

(所影响的行数为 5 行)
--*/

③ sql 怎么递归查询的方法:

1.创建测试表,createtabletest_connect(idnumber,p_idnumber);

④ sql语句实现递归查询所有节点,mysql和oracle都能用的

首先说一下Oracle的递归查询,相信大部分人都知道很简单。无非start with connect by 函数。下面是从pId向子节点递归查询的例子,unId是数据库表中的主键。

如果是从子节点递归到父节点查询,就把start with 换成unid,prior左右对换

下面再讲MySql 的递归查询方式。MySql没有Oracle的强大功能,虽然都是同一个公司的产品。所以只能靠自己写。有很多方法,用sql去循环查询,或者写存储过程,我这里只提供一种。就是新建一个function函数。

表结构不说了,无非就是 Id ,pId,其他列。下面是创建一个递归查询子节点的函数

DROP FUNCTION IF EXISTS queryChildrenPowerInfo;

CREATE FUNCTION `queryChildrenPowerInfo` (powerId VARCHAR(2000))

RETURNS VARCHAR(2000)

BEGIN

DECLARE sTemp VARCHAR(2000);

DECLARE sTempChd VARCHAR(2000);

SET sTemp = '$';

SET sTempChd = cast(powerId as CHAR);

WHILE sTempChd is not NULL DO

SET sTemp = CONCAT(sTemp, ',', sTempChd);

SELECT group_concat(id) INTO sTempChd FROM t_discretionary_power where FIND_IN_SET(pId,sTempChd)>0;

END WHILE;

return sTemp;

调用的时候:select queryChildrenPowerInfo(""); 该语句会返回Id和父Id等于传入参数powerId的一个字符串,中间有逗号隔开如图

下面这句代码的意思是,查询出 t_discretionary_power 表中,t.id 等于上面查询出的结果集的数据。FIND_IN_SET(A,B)是MYSQL的函数。意思是查找在B集合中有A的数据。相当于In

select t.* from t_discretionary_power t where FIND_IN_SET(t.id,queryChildrenPowerInfo(''))

⑤ 如何用SQL语句,在一个表里面判断逐级编码以及逐级对应名称,从而实现末级编码对应逐级拼接名称

SQL带递归的语法 参考如下sqlserver 真他数据库也有类似
IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE tb
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' , '松岗镇')
GO
SELECT * FROM tb AS t

DECLARE @ID VARCHAR(3)
--查询ID = '001'的所有子节点
SET @ID = '007'
;WITH Temp AS (
SELECT id,pid,NAME FROM tb AS t WHERE t.id=@ID
UNION ALL
SELECT t2.id,t2.pid,t2.NAME FROM tb t2 INNER JOIN Temp tm on t2.pid=tm.ID
)
SELECT * FROM Temp AS t WHERE id!=@ID

⑥ SQL递归查询知多少

1、基本概念

公用表表达式 (CTE) 可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集。公用表表达式可以包括对自身的引用,这种表达式称为递归公用表表达式。

创建递归查询。有关详细信息,请参阅使用公用表表达式的递归查询。
在不需要常规使用视图时替换视图,也就是说,不必将定义存储在元数据中。
启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。
在同一语句中多次引用生成的表。

MSDN上对CTE的介绍
T-SQL查询进阶--详解公用表表达式(CTE)

CTE 的基本语法结构如下:

WITH expression_name [ ( column_name [,...n] ) ]
AS
( CTE_query_definition )
--只有在查询定义中为所有结果列都提供了不同的名称时,列名称列表才是可选的。
--运行 CTE 的语句为:
SELECT <column_list> FROM expression_name;

即三个部分:

公用表表达式的名字(在WITH关键字之后)
查询的列名(可选)
紧跟AS之后的SELECT语句(如果AS之后有多个对公用表的查询,则只有第一个查询有效)

⑦ SQL递归查询所有子节点

你这样设计的表用递归来显示最恰当 我刚刚好有这个的代码 发给你参考下吧
/// <summary>
/// 绑定根节点
/// </summary>
/// <param name="id"></param>
/// <param name="ddlList"></param>
public void BindSysMenu(string id, DropDownList ddlList)
{
ListItem ll = new ListItem();
ll.Text = "╋--请选择-----";
ll.Value = "-1";
ddlList.Items.Add(ll);
DataTable dt = new ManageContentInfoBll().GetWName(id).Tables[0];
foreach (DataRow dr in dt.Rows)
{
ListItem li = new ListItem();
li.Text = "╋" + dr["W_Name"].ToString();
li.Value = dr["W_ID"].ToString();
ddlList.Items.Add(li);
BindSysMenuChild((dr["W_ID"].ToString()), ddlList, "├—");
}
}

/// <summary>
/// 绑定子节点
/// </summary>
public void BindSysMenuChild(string id, DropDownList ddlList, String separtor)
{
DataTable dt = new ManageContentInfoBll().GetWName(id).Tables[0];
foreach (DataRow dr in dt.Rows)
{
ListItem li = new ListItem();
li.Text = separtor + dr["W_Name"].ToString();
li.Value = dr["W_ID"].ToString();
string separtor_ = separtor + "——";
ddlList.Items.Add(li);
BindSysMenuChild(dr["W_ID"].ToString(), ddlList, separtor_);
}

}
sql 语句 很简单的
select * from WebSubjectMenu where W_Logo ="+id+"
W_Logo 是上级的ID
希望对你有帮助吧。

热点内容
漏油器密码怎么改密码 发布:2024-11-26 20:30:11 浏览:13
linux编码命令 发布:2024-11-26 20:23:13 浏览:800
密码加密工具 发布:2024-11-26 20:23:06 浏览:691
如何破解加密的wifi 发布:2024-11-26 20:10:29 浏览:430
c脚本检查 发布:2024-11-26 19:56:34 浏览:393
服务器ip控制系统叫什么 发布:2024-11-26 19:56:31 浏览:746
ecshop文件夹权限 发布:2024-11-26 19:55:05 浏览:73
编程123 发布:2024-11-26 19:52:52 浏览:949
python数组排序排序算法 发布:2024-11-26 19:50:16 浏览:969
如保编程 发布:2024-11-26 19:29:58 浏览:812