4

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

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

4

8 回答 8

3

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

select * from areas where path like '%/1/%'
于 2009-10-26T13:55:57.307 回答
2

您可以使用

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

如果您存储了路径

于 2009-10-26T13:58:54.917 回答
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/%' 这样的路径显然是更好的解决方案。

于 2009-10-26T14:14:55.633 回答
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.

于 2009-10-26T14:26:46.123 回答
0

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

于 2009-10-26T14:00:46.363 回答
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
于 2009-10-26T14:09:44.503 回答
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

我一直重复使用这个。

于 2009-10-26T14:13:51.250 回答
0

SQLite:

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

于 2009-10-26T14:18:17.043 回答