Sql获取父母的所有孩子

时间:2009-10-26 13:52:20

标签: sql recursion parent

假设我有一个区域表(id,parentId,name,path)。

鉴于Id,我想让所有孩子(包括孩子的孩子,递归地)得到给定区域。

我确实存储了从父母到孩子的路径。

示例:

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/

因此,在询问纽约的孩子时,查询应该返回布朗克斯,manh,upwest和mideast。而且不仅仅是布朗克斯和曼。

8 个答案:

答案 0 :(得分:3)

将返回id为1的所有城市儿童区域(例如纽约)。您可以将该号码更改为任何其他城市,以便将其返回给孩子

select * from areas where path like '%/1/%'

答案 1 :(得分:2)

您可以使用

SELECT * FROM Areas WHERE Path LIKE '%/1/%'

如果您已存储路径

答案 2 :(得分:1)

如果你有一个固定的数字深度,你知道你永远不会深入,这将做你想要的:

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 /%'之类的路径显然是更好的解决方案。

答案 3 :(得分:1)

MySQL

SELECT  *
FROM    Areas ap
JOIN    Areas ac
ON      ac.path > ap.path
        AND ac.path < CONCAT(ap.path, ':')
WHERE   ap.id = 1

PostgreSQLOracle

SELECT  *
FROM    Areas ap
JOIN    Areas ac
ON      ac.path > ap.path
        AND ac.path < ap.path || ':'
WHERE   ap.id = 1

SQL Server

SELECT  *
FROM    Areas ap
JOIN    Areas ac
ON      ac.path > ap.path
        AND ac.path < ap.path + ':'
WHERE   ap.id = 1

LIKE(没有双关语)不同,这将使用path上的索引。

答案 4 :(得分:0)

在Oracle SQL中查找START WITH和CONNECT BY。 这样,您就可以选择具有层次关系的数据(树状)。

答案 5 :(得分:0)

不知道您正在使用的数据库:如果是SQL Server,请使用公用表表达式(CTE

否则,

您需要某种代码或存储过程。使用psuedoCode

   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

答案 6 :(得分:0)

试试这个:

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

我一直在重复使用它。

答案 7 :(得分:0)

SQLite的:

SELECT * FROM Areas where path like (SELECT path || '%' FROM Areas WHERE area="New York")