Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql获取父级的所有子级_Sql_Recursion_Parent - Fatal编程技术网

Sql获取父级的所有子级

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/ 因此,当询问什么是纽约的孩子时,查询应该返回布朗克斯、曼恩、西北

假设我有一个区域表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/

因此,当询问什么是纽约的孩子时,查询应该返回布朗克斯、曼恩、西北和中东。不仅布朗克斯区和曼恩区。

还将归还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