Sql获取父级的所有子级
假设我有一个区域表id、parentId、名称和路径 给定一个Id,我希望以递归方式将所有children的children的children包含在给定区域中 我确实在路径中存储了从父母到孩子的路径 例如:Sql获取父级的所有子级,sql,recursion,parent,Sql,Recursion,Parent,假设我有一个区域表id、parentId、名称和路径 给定一个Id,我希望以递归方式将所有children的children的children包含在给定区域中 我确实在路径中存储了从父母到孩子的路径 例如: 1 NULL New York /1/ 2 1 BRONX /1/2/ 3 1 MANH /1/3/ 4 3 UpWest /1/3/4/ 5 3 MidEast /1/3/5/ 因此,当询问什么是纽约的孩子时,查询应该返回布朗克斯、曼恩、西北
1 NULL New York /1/
2 1 BRONX /1/2/
3 1 MANH /1/3/
4 3 UpWest /1/3/4/
5 3 MidEast /1/3/5/
因此,当询问什么是纽约的孩子时,查询应该返回布朗克斯、曼恩、西北和中东。不仅布朗克斯区和曼恩区。还将归还id为1的所有城区,例如纽约。你可以把这个号码改成其他任何一个城市,把它的孩子也换回来
select * from areas where path like '%/1/%'
你可以用
SELECT * FROM Areas WHERE Path LIKE '%/1/%'
如果存储了路径,请在Oracle SQL中查找START WITH和CONNECT BY。
通过这种方式,您可以选择具有层次关系树的数据,如。不知道您使用的是什么数据库:如果是SQL Server,请使用公共表表达式 否则, 您需要某种代码或存储过程。。使用伪代码
Assuming @Parent is Primary key of Area record you want children of...
--Create Temp table (Does your DB have temp Tables) of Keys
-- Say it's called 'Children'
-- -- make this a temmp table...
-- In SQL Server syntax uses a #.
-- Create Table #Table... ( or use table variable Declare @Children Table ... ),
-- Oracle, MySql have their own syntax...
Create Table Children
(PK Integer Primary Key Not Null)
-- -------------------------
Insert Children(PK)
Select PK From Area
Where Parent = @Parent
-- -----------------------
While Exists (Select * From 'Children' As C
Where Exists
(Select * From Area
Where parent = C.PK
And PK Not In
(Select PK From 'Children')))
Begin
Insert Children(PK)
Select PK From Area
Where Parent In (Select PK From Children)
And PK Not In (Select PK From Children)
End
--Then join temp table to Area table and return results
Select a.* From Area a
Join Children C On C.PK = A.PK
试试这个:
declare @id int
select @id = 1;
with CustParent (ParentID,ChildID)
as
(
select o.ParentID, o.ChildID
from Customer o
where o.ID = @id
union all
select cpc.ParentID ,cpc.ID
from Customer cpc
inner join CustParent cp on cp.ChildID = cpc.ParentID
)
Select Customer.ChildID, Customer.ParentID
from Customer
inner join CustParent cp on cp.ChildID = Customer.ChildID
我一直在重复使用它。如果你有一个设定的数字深度,你知道你永远不会超过这个深度,那么你会做你想要的:
select * from areas a1
join areas a2 on a1.id = a2.parent
join areas a3 on a2.id = a3.parent
join areas a4 on a3.id = a4.parent
join areas a5 on a4.id = a5.parent
where a1 = 1; --or whatever value you're searching for.
编辑:
但是,如果您已经保存了我直到现在才注意到的路径,那么像“%/1/%”这样的路径显然是更好的解决方案。SQLite:
从路径类似的区域中选择*
从MySQL中area=New York的区域中选择路径| |'%:
在SQL Server中:
与非双关语不同,这将在路径上使用索引。中东路径应该是“/1/3/5/”?:是数字后的第一个ASCII字符:9的ASCII代码为57,:的ASCII代码为58。这是一个粗略的过滤器,它依赖于假设路径中除了数字和斜杠之外什么都没有。
SELECT *
FROM Areas ap
JOIN Areas ac
ON ac.path > ap.path
AND ac.path < CONCAT(ap.path, ':')
WHERE ap.id = 1
SELECT *
FROM Areas ap
JOIN Areas ac
ON ac.path > ap.path
AND ac.path < ap.path || ':'
WHERE ap.id = 1
SELECT *
FROM Areas ap
JOIN Areas ac
ON ac.path > ap.path
AND ac.path < ap.path + ':'
WHERE ap.id = 1