sql语句中如何实现递归查询?

时间:2022-09-19 10:52:03
我有两张表:   
  产品表products:   
  productsID     //产品编号
  productname     //产品名称   
  ProductTypeID //所属类型编号  
    
  产品类型表ProductType:   
  ProductTypeID    //类型编号  
  TypeName         //类型名称   
  ParentID         //上级类型编号   
  Level            //层次
  ProductKey       //类型标识  

在ProductType表中通过ProductTypeID    (上级产品编码)实现类型的所属关系和层次划分,分类型根类标识是“0”   
  假设有产品类型的层次如下:   
    
  产品类型a   
            产品类型a1   
                      产品类型a11   
                      产品类型a12   
                      产品类型a13   
            产品类型a2   
                      产品类型a21   
                              产品类型a211   
                      产品类型a22   
                      产品类型a23   
  
   
我现在想查询产品类型a 中的所有产品如何在一个sql语句中查出来? 

29 个解决方案

#1


定义一张临时表!

#2


lz:产品表products和产品类型表ProductType两个表的部分数据发给我,
我来试试,解决后马上给你回复,OK?

邮箱:sdl2002lyx@163.com
注:最好用acess打包发给我,这样会块些。

#3


select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;

#4


要用一个中间表;

用存储过程递归将结果插入中间表.

#5


在SQL SERVER 2000 中你可以先一些自定义函数,或一些存储过程,实现递归。应该能够解决问题。

#6


没必要用递归吧.再说递归还有嵌套次数的限制呢.万一出问题就惨了

#7


不知道你的分类ID是不是有规律,如果子类ID是在父类ID下加了一串的话,比如PID = A,CID=A01

你可以这样吧SELECT ......WHERE ProductTypeID like'A%'

或者定级 SELECT ......WHERE ProductTypeID like'A__'

以上语句跟设计有关

#8


学习!帮顶

#9


UP.............

#10


select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;

#11


我的数据库是 SQL server2000 

“select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;”

这个只能在SQL server 2005 可行而在2000中不行。

#12


这是我写的一个涵数


CREATE FUNCTION GetSubtreeInfo ( @manager_id AS char(5)) 
RETURNS @treeinfo table ( ProductTypeID int  NOT NULL )
 AS 
  BEGIN 
   DECLARE @level AS int 
    select  @level = 0 
  insert into  @treeinfo select   ProductTypeID from  ProductType where ProductTypeID = @manager_id 

   while @@ROWCOUNT > 0 
  begin
  set @level = @level + 1 
  insert into  @treeinfo select  E.ProductTypeID, @level from  ProductType as E JOIN @treeinfo as T 
  on E.[ProductTypeID] = T.[ProductTypeID] AND T.[Level] = @level

#13


不需要用到递归...

这是个设计问题...不是SQL问题...

#14


只有加一个深度的字段,不需要这么搞递归,浪费

#15


普尔世纪是一家高新软件开发企业,秉持着创新(Innovation)、整合(Intergration)、速度(Acceleration)与国际化(Internationalization)的愿景,及其专业的软件开和软件销售,通信设备销售。通过普尔世纪一支精锐的软件开发、销售队伍,为客户提供高竞争力与创新的软件产品、通信设备。

现因业务发展,需招聘2名技术人员
1. 精通 c#和c++语言
2. 具银行行业软件开发经验佳
3. 有良好的沟通、领悟能力
4. 有较好的团队合作精神
7. 有良好的敬业精神,能够承受较大的工作压力
工资薪金待遇:
适用期三个月,适用期薪金3000,转为正式员工的薪金适工作能力再议,如员工在工作中为公司的发展做出较大贡献者,公司视情况给予分派公司股份.


有意者可以将简历发到的我邮箱yanmeiying_aa@sina.com

#16


招聘也不写地址

#17


占个位子

#18


用个游标就行了

#19


不能够递归的,假如数据量大的话这样的效率是不是太低了?
感觉楼主的产品类型表ProductType设计得不合理。但我不知道如何设计

强烈关注。

#20


我做的是把每个类别放入一个表中,这样做比较好点

#21


--這是我以前寫的兩個函數,和你需求有些類似,你可以參考下。

--建立測試環境
Create Table Categories
(Cate_Id int,
Name nvarchar(50))
Create Table Categories_Relations
(Parent_Id int,
Child_Id int)
Insert Categories Select 1, 'A1'
Union All Select 2, 'A2'
Union All Select 3, 'A3'
Union All Select 5, 'A5'
Union All Select 6, 'A6'
Union All Select 7, 'A7'

Insert Categories_Relations Select 1, 2
Union All Select 1, 3
Union All Select 3, 5
Union All Select 5, 6
Union All Select 6, 7
GO
--建立函數
--得到所有的子節點
Create Function GetChildren(@Cate_Id Int)
Returns @Tree Table (Child_Id Int)
As
Begin
Insert @Tree Select Child_Id From Categories_Relations Where Parent_Id = @Cate_Id
While @@Rowcount > 0
Insert @Tree Select A.Child_Id From Categories_Relations A Inner Join @Tree B On A.Parent_Id = B.Child_Id And A.Child_Id Not In (Select Child_Id From @Tree)
Return
End
GO

--得到所有的父節點
Create Function GetParent(@Cate_Id Int)
Returns @Tree Table (Parent_Id Int)
As
Begin
Insert @Tree Select Parent_Id From Categories_Relations Where Child_Id = @Cate_Id
While @@Rowcount > 0
Insert @Tree Select A.Parent_Id From Categories_Relations A Inner Join @Tree B On A.Child_Id = B.Parent_Id And A.Parent_Id Not In (Select Parent_Id From @Tree)
Return
End
GO
--測試
Select * From dbo.GetChildren(5)
Select * From dbo.GetParent(5)
GO
--刪除測試環境
Drop Table Categories, Categories_Relations
Drop Function GetParent, GetChildren
--結果
/*
Child_Id
6
7

Parent_Id
3
1
*/

#22


不能用递归就用递推么!

所有递归都能转化为递推的

用递推就没有层数限制了


zhangqiang1985(白开水) 的答案是正解

但是有个小BUG

多测试一下while @@ROWCOUNT > 0 这个就知道了

这个 @@ROWCOUNT 变化太快,不能在这里判断,需要用IF 判断,这个多测试几次就知道了~~~

#23


--根據你的表改寫的函數

--建立測試環境
Create Table products
(productsID int,
productname nvarchar(50),
ProductTypeID int)

Create Table ProductType
(ProductTypeID int,
Typeproductname nvarchar(50),
ParentID int,
Level int,
ProductKey int)
Insert products Select 1, 'A1', '1'
Union All Select 2, 'A2', '2'
Union All Select 3, 'A3', '3'
Union All Select 5, 'A5', '3'
Union All Select 6, 'B1', '5'
Union All Select 7, 'B2', '6'

Insert ProductType Select 1, 'A', 0, 1, 1
Union All Select 2, 'A1', 1, 2, 1
Union All Select 3, 'A2', 2, 3, 1
Union All Select 5, 'B', 0, 1, 2
Union All Select 6, 'B1', 5, 2, 2
GO
--建立函數
--得到所有的子節點
Create Function F_GetChildren(@Typeproductname nvarchar(50))
Returns @Tree Table (ProductTypeID Int)
As
Begin
Insert @Tree Select ProductTypeID From ProductType Where Typeproductname = @Typeproductname
While @@Rowcount > 0
Insert @Tree Select A.ProductTypeID From ProductType A Inner Join @Tree B On A.ParentID = B.ProductTypeID And A.ProductTypeID Not In (Select ProductTypeID From @Tree)
Return
End
GO
--測試
Select * From products Where ProductTypeID In (Select ProductTypeID From dbo.F_GetChildren('A'))
GO
--刪除測試環境
Drop Table products, ProductType
Drop Function F_GetChildren
--結果
/*
productsID productname ProductTypeID
1 A1 1
2 A2 2
3 A3 3
5 A5 3
*/

#24


ProductType表中有加几个字段
1,当前层数
2.编码 比如 3位为一层,001 002 或 0001001 0001002 这样依此类推

#25


學習

#26


sql05里用CTE
sql2000写sp

#27


好像有些自欺欺人,没必要把类型分那么复杂啊。分了有什么好处啊。不明白

#28


设计好表,并建立好索引,

上面的与BOM类似,不需要查询递归,采用查询递归是一种最笨的办法.
建一个临时表,用存储过程实现展开.

还有,一条语句是实现不了的,如果有多层的话,你怎么办?所以要考虑一个通用的.

#29


up

#1


定义一张临时表!

#2


lz:产品表products和产品类型表ProductType两个表的部分数据发给我,
我来试试,解决后马上给你回复,OK?

邮箱:sdl2002lyx@163.com
注:最好用acess打包发给我,这样会块些。

#3


select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;

#4


要用一个中间表;

用存储过程递归将结果插入中间表.

#5


在SQL SERVER 2000 中你可以先一些自定义函数,或一些存储过程,实现递归。应该能够解决问题。

#6


没必要用递归吧.再说递归还有嵌套次数的限制呢.万一出问题就惨了

#7


不知道你的分类ID是不是有规律,如果子类ID是在父类ID下加了一串的话,比如PID = A,CID=A01

你可以这样吧SELECT ......WHERE ProductTypeID like'A%'

或者定级 SELECT ......WHERE ProductTypeID like'A__'

以上语句跟设计有关

#8


学习!帮顶

#9


UP.............

#10


select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;

#11


我的数据库是 SQL server2000 

“select level,TypeName
from ProductType t
START WITH t.ParentID=0
CONNECT BY PRIOR t.ProductTypeID= t.ParentID;”

这个只能在SQL server 2005 可行而在2000中不行。

#12


这是我写的一个涵数


CREATE FUNCTION GetSubtreeInfo ( @manager_id AS char(5)) 
RETURNS @treeinfo table ( ProductTypeID int  NOT NULL )
 AS 
  BEGIN 
   DECLARE @level AS int 
    select  @level = 0 
  insert into  @treeinfo select   ProductTypeID from  ProductType where ProductTypeID = @manager_id 

   while @@ROWCOUNT > 0 
  begin
  set @level = @level + 1 
  insert into  @treeinfo select  E.ProductTypeID, @level from  ProductType as E JOIN @treeinfo as T 
  on E.[ProductTypeID] = T.[ProductTypeID] AND T.[Level] = @level

#13


不需要用到递归...

这是个设计问题...不是SQL问题...

#14


只有加一个深度的字段,不需要这么搞递归,浪费

#15


普尔世纪是一家高新软件开发企业,秉持着创新(Innovation)、整合(Intergration)、速度(Acceleration)与国际化(Internationalization)的愿景,及其专业的软件开和软件销售,通信设备销售。通过普尔世纪一支精锐的软件开发、销售队伍,为客户提供高竞争力与创新的软件产品、通信设备。

现因业务发展,需招聘2名技术人员
1. 精通 c#和c++语言
2. 具银行行业软件开发经验佳
3. 有良好的沟通、领悟能力
4. 有较好的团队合作精神
7. 有良好的敬业精神,能够承受较大的工作压力
工资薪金待遇:
适用期三个月,适用期薪金3000,转为正式员工的薪金适工作能力再议,如员工在工作中为公司的发展做出较大贡献者,公司视情况给予分派公司股份.


有意者可以将简历发到的我邮箱yanmeiying_aa@sina.com

#16


招聘也不写地址

#17


占个位子

#18


用个游标就行了

#19


不能够递归的,假如数据量大的话这样的效率是不是太低了?
感觉楼主的产品类型表ProductType设计得不合理。但我不知道如何设计

强烈关注。

#20


我做的是把每个类别放入一个表中,这样做比较好点

#21


--這是我以前寫的兩個函數,和你需求有些類似,你可以參考下。

--建立測試環境
Create Table Categories
(Cate_Id int,
Name nvarchar(50))
Create Table Categories_Relations
(Parent_Id int,
Child_Id int)
Insert Categories Select 1, 'A1'
Union All Select 2, 'A2'
Union All Select 3, 'A3'
Union All Select 5, 'A5'
Union All Select 6, 'A6'
Union All Select 7, 'A7'

Insert Categories_Relations Select 1, 2
Union All Select 1, 3
Union All Select 3, 5
Union All Select 5, 6
Union All Select 6, 7
GO
--建立函數
--得到所有的子節點
Create Function GetChildren(@Cate_Id Int)
Returns @Tree Table (Child_Id Int)
As
Begin
Insert @Tree Select Child_Id From Categories_Relations Where Parent_Id = @Cate_Id
While @@Rowcount > 0
Insert @Tree Select A.Child_Id From Categories_Relations A Inner Join @Tree B On A.Parent_Id = B.Child_Id And A.Child_Id Not In (Select Child_Id From @Tree)
Return
End
GO

--得到所有的父節點
Create Function GetParent(@Cate_Id Int)
Returns @Tree Table (Parent_Id Int)
As
Begin
Insert @Tree Select Parent_Id From Categories_Relations Where Child_Id = @Cate_Id
While @@Rowcount > 0
Insert @Tree Select A.Parent_Id From Categories_Relations A Inner Join @Tree B On A.Child_Id = B.Parent_Id And A.Parent_Id Not In (Select Parent_Id From @Tree)
Return
End
GO
--測試
Select * From dbo.GetChildren(5)
Select * From dbo.GetParent(5)
GO
--刪除測試環境
Drop Table Categories, Categories_Relations
Drop Function GetParent, GetChildren
--結果
/*
Child_Id
6
7

Parent_Id
3
1
*/

#22


不能用递归就用递推么!

所有递归都能转化为递推的

用递推就没有层数限制了


zhangqiang1985(白开水) 的答案是正解

但是有个小BUG

多测试一下while @@ROWCOUNT > 0 这个就知道了

这个 @@ROWCOUNT 变化太快,不能在这里判断,需要用IF 判断,这个多测试几次就知道了~~~

#23


--根據你的表改寫的函數

--建立測試環境
Create Table products
(productsID int,
productname nvarchar(50),
ProductTypeID int)

Create Table ProductType
(ProductTypeID int,
Typeproductname nvarchar(50),
ParentID int,
Level int,
ProductKey int)
Insert products Select 1, 'A1', '1'
Union All Select 2, 'A2', '2'
Union All Select 3, 'A3', '3'
Union All Select 5, 'A5', '3'
Union All Select 6, 'B1', '5'
Union All Select 7, 'B2', '6'

Insert ProductType Select 1, 'A', 0, 1, 1
Union All Select 2, 'A1', 1, 2, 1
Union All Select 3, 'A2', 2, 3, 1
Union All Select 5, 'B', 0, 1, 2
Union All Select 6, 'B1', 5, 2, 2
GO
--建立函數
--得到所有的子節點
Create Function F_GetChildren(@Typeproductname nvarchar(50))
Returns @Tree Table (ProductTypeID Int)
As
Begin
Insert @Tree Select ProductTypeID From ProductType Where Typeproductname = @Typeproductname
While @@Rowcount > 0
Insert @Tree Select A.ProductTypeID From ProductType A Inner Join @Tree B On A.ParentID = B.ProductTypeID And A.ProductTypeID Not In (Select ProductTypeID From @Tree)
Return
End
GO
--測試
Select * From products Where ProductTypeID In (Select ProductTypeID From dbo.F_GetChildren('A'))
GO
--刪除測試環境
Drop Table products, ProductType
Drop Function F_GetChildren
--結果
/*
productsID productname ProductTypeID
1 A1 1
2 A2 2
3 A3 3
5 A5 3
*/

#24


ProductType表中有加几个字段
1,当前层数
2.编码 比如 3位为一层,001 002 或 0001001 0001002 这样依此类推

#25


學習

#26


sql05里用CTE
sql2000写sp

#27


好像有些自欺欺人,没必要把类型分那么复杂啊。分了有什么好处啊。不明白

#28


设计好表,并建立好索引,

上面的与BOM类似,不需要查询递归,采用查询递归是一种最笨的办法.
建一个临时表,用存储过程实现展开.

还有,一条语句是实现不了的,如果有多层的话,你怎么办?所以要考虑一个通用的.

#29


up