Как получить дочернюю от основной записи из таблицы SQL - PullRequest
0 голосов
/ 28 октября 2019

У меня есть таблица для бухгалтерских книг. Он состоит из MasterID в качестве уникального идентификатора и parentID для присоединения.

Модель моей таблицы

enter image description here

Как и на рисунке, мой родительский регистр - «A». «B» является прямым потомком «A». «C» является прямым потомком «B», а «D» является прямым потомком «C». Я хочу выбрать запрос, чтобы выбрать все дочерние элементы «A». то есть результат будет B, C, D. Я новичок в SQL. Я попробовал цикл while для этого, но был доступен только прямой ребенок. Я не могу сделать логику для требования. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Это типичный иерархический запрос. Рассмотрим решение, которое использует рекурсивный cte:

with cte as (
    select masterID rootID, masterID, name, parentid
    from mytable    
    where parentID is null
    union all
    select c.rootID, t.masterID, t.name, t.parentID
    from mytable t
    inner join cte c on c.masterID = t.parentID 
)
select * from cte

Как прокомментировал The Impaler, вы можете при необходимости изменить начальное условие where parentID is null на id другого узла.

Сваши примерные данные, это дает:

rootID | masterID | name | parentid
-----: | -------: | :--- | -------:
     1 |        1 | A    |     <em>null</em>
     1 |        2 | B    |        1
     1 |        3 | C    |        2
     1 |        4 | D    |        3

Обратите внимание, что я отслеживал идентификатор корневого объекта, поэтому легче понять, что происходит, если в ваших данных есть несколько корней.

Вы также можете использовать корень для генерации простого списка детей:

with cte as (
    select masterID rootID, masterID, name, parentid
    from mytable    
    where parentID is null
    union all
    select c.rootID, t.masterID, t.name, t.parentID
    from mytable t
    inner join cte c on c.masterID = t.parentID 
)
select rootID, string_agg(masterID, ',') childrenID from cte group by rootID
rootID | childrenID
-----: | :---------
     1 | 1,2,3,4         

Демонстрация на DB Fiddle

0 голосов
/ 28 октября 2019

Вот опция, которая использует HierarchyID

Клавиши диапазона (R1 / R2) в конечном выборе являются необязательными.

Пример

Declare @YourTable table (MasterID  int ,name varchar(50), ParentID int);
Insert Into @YourTable values 
( 1, 'A', null),
( 2, 'B', 1),
( 3, 'C', 2),
( 4, 'D', 3)

Declare @Top   int         = 2           --<<  Sets top of Hier Try NULL for entire hier
Declare @Nest  varchar(25) = '|-----'    --<<  Optional: Added for readability

;with cteP as (
      Select MasterID
            ,ParentID 
            ,Name 
            ,HierID = convert(hierarchyid,concat('/',MasterID,'/'))
      From   @YourTable 
      Where  IsNull(@Top,-1) = case when @Top is null then isnull(ParentID ,-1) else MasterID end
      Union  All
      Select MasterID  = r.MasterID
            ,ParentID  = r.ParentID 
            ,Name   = r.Name
            ,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.MasterID,'/'))
      From   @YourTable r
      Join   cteP p on r.ParentID  = p.MasterID)
Select R1    = Row_Number() over (Order By HierID)
      ,R2    = (Select count(*) From cteP where HierID.ToString() like A.HierID.ToString()+'%')
      ,Lvl   = HierID.GetLevel()
      ,MasterID
      ,ParentID
      ,Name  = Replicate(@Nest,HierID.GetLevel()-1) + Name
      ,HierID
      ,HierID_String = HierID.ToString()
 From cteP A
 Order By A.HierID

Возвращает

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...