Sql Получить всех детей родителей - PullRequest
3 голосов
/ 26 октября 2009

Допустим, у меня есть таблица областей (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/

Поэтому, когда спрашивают, кто такие дети в Нью-Йорке, запрос должен возвращать бронкс, мань, юго-запад и средний восток. и не только бронкс и мань.

Ответы [ 8 ]

3 голосов
/ 26 октября 2009

Возвращает все области, которые являются детьми города с идентификатором 1 (например, Нью-Йорк). Вы можете изменить этот номер на любой другой город, чтобы вернуть его детям тоже

select * from areas where path like '%/1/%'
2 голосов
/ 26 октября 2009

Вы можете использовать

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

если у вас есть сохраненный путь

1 голос
/ 26 октября 2009

В MySQL:

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

В PostgreSQL и Oracle:

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

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

1 голос
/ 26 октября 2009

Если у вас есть заданная глубина номера, которую вы знаете, вы никогда не пойдете глубже, чем это сделает то, что вы хотите:

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.

Edit: Однако, если у вас уже есть сохраненный путь (который я не замечал до сих пор), путь типа «% / 1 /%», несомненно, является лучшим решением.

0 голосов
/ 26 октября 2009

SQLite:

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

0 голосов
/ 26 октября 2009

Попробуйте это:

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

Я все время использую это.

0 голосов
/ 26 октября 2009

Не знаю, какую базу данных вы используете: если 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
0 голосов
/ 26 октября 2009

Ищите START WITH и CONNECT BY в Oracle SQL. таким образом, вы можете выбрать данные с иерархическими отношениями (в виде дерева).

...