2009-10-26 113 views
3

可以说我有一个区域表(id,parentId,名称,路径)。Sql获取父项的所有子项

给定一个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/ 

所以要求有哪些纽约的孩子们时,查询应该返回布朗克斯,农德孟,upwest和中东。而不只是布朗克斯和曼。

+2

Shoud the MidEast path be'/ 1/3/5 /'? – 2009-10-26 14:18:12

+0

是纠正它,thx – pdiddy 2009-10-26 14:26:26

回答

3

将返回所有ID为1的城市的儿童区域(例如纽约)。您可以在数更改为任何其他城市返回它的孩子太

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

编辑处理超过9行:) – Trevor 2009-10-26 13:58:21

2

您可以使用

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

如果你的路径存储

0

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

0

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

否则,

你需要某种形式的代码或存储过程中使用..伪码

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 
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 

我雷乌斯这是所有的时间。

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

0

SQLite的:

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

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的索引。

+0

你能向我解释这是如何工作的?我不明白':'? – pdiddy 2009-10-27 14:59:52

+0

':'是数字后的第一个ASCII字符:'9'具有'''ASCII'代码'57',''''具有'''ASCII'代码'58'。这是一个粗略的过滤器,依赖于你没有任何东西,只有你的路径中的数字和斜线。 – Quassnoi 2009-10-27 17:30:13

相关问题