Получение данных иерархии до последнего дочернего элемента - sql server

У меня такая структура таблицы. Я хочу создать запрос только для иерархических данных до последнего дочернего элемента, без ссылки на родительский элемент снова.

Структура таблицы:

    ParentId    ChildId
    -------------------
    NULL        6000101
    6000101     6000102
    6000101     6000106
    6000101     6000107
    6000102     6000103
    6000102     6000104
    6000102     6000105
    6000103     6000101
    6000104     6000101
    6000105     6000101
    6000106     6000101
    6000106     6000102
    6000107     6000102
    6000107     6000105

Текущее изображение структуры данных

Желаемая структура или набор результатов:

    ParentId  ChildId 
    ---------------------
    NULL      6000101
    6000101   6000102
    6000101   6000106
    6000101   6000107
    6000102   6000103
    6000102   6000104
    6000102   6000105

Желаемый результат Изображение

Кто-нибудь может помочь, пожалуйста?

Большинству людей здесь нужен форматированный текст, а не изображения (или ссылки на изображения).

jarlh 10.08.2018 17:07

Привет, мне очень жаль, но я попытался отформатировать его, но он не работает, следует ли мне использовать теги html для форматирования?

Sandipan 10.08.2018 17:09

При редактировании записывайте данные в соответствующие столбцы. Поместите 4 символа <пробел> сначала в каждую строку и перед ней пустую строку.

jarlh 10.08.2018 17:11

Хорошо. Дай мне попробовать. Как сделать разрыв строки для каждой строки?

Sandipan 10.08.2018 17:16

Пустая строка нужна только один раз перед разделом выборочных данных.

jarlh 10.08.2018 17:17

Извините, я не заставил работать нормально, но придумал отредактированный.

Sandipan 10.08.2018 17:26

Также можно выделить блок кода и нажать кнопку фигурных скобок {} (или CTRL + K)

Aaron Dietz 10.08.2018 17:27

Я сделал и проверил отредактированный.

Sandipan 10.08.2018 17:31

Значит, у дочерней записи может быть несколько родителей?

Josh Jay 10.08.2018 17:45

Можете ли вы пояснить, чего вы пытаетесь достичь? Мне неясно, чего вы ожидаете от желаемого результата.

ErikusMaximus 10.08.2018 17:47

Правка выглядит хорошо. Как спрашивали другие, какова логика ваших ожидаемых результатов? Почему рассматривается первый ребенок ParentID = 6000102, а не все остальные?

Aaron Dietz 10.08.2018 18:28

Пожалуйста, определите, как работают отношения между ParentID и ChildID. Как сказал @ErikusMaximus, хотя визуально вы показали желаемый результат, неясно, как данные связаны с его получением.

Critical Error 10.08.2018 18:30

Спасибо всем за ваши ответы. Ниже ответьте, что мне нужно. Но чтобы прояснить ваши запросы, это сценарий с несколькими родителями, в котором у дочернего элемента может быть более одного родителя, например блок-схема, мне нужно получить данные детализации до последнего дочернего элемента, не ссылаясь снова на его какой-либо из родительских элементов.

Sandipan 10.08.2018 20:24
0
13
495
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обычно при запросе иерархии можно использовать рекурсивное общее табличное выражение, но поскольку у вас есть циклические ссылки в ваших данных, вам нужно будет использовать цикл.

Предположим, ваша исходная таблица называется MyTable. Вы захотите создать таблицу (временную или другую), которая будет содержать очищенную иерархию:

create table MyHierarchy (
  ParentId int null
  ,ChildId int not null
  ,[Level] int not null
);

Затем вы введете свою корневую родительскую запись и зациклитесь, пока не дойдете до круговых ссылок:

-- insert root parent record
insert into MyHierarchy
select
    *
    ,0 as [Level]
from
    MyTable
where
    ParentId is null;

-- loop until you reach a circular reference
while @@ROWCOUNT > 0
begin
    insert into MyHierarchy
    select
        MyTable.*
        ,MyHierarchy.[Level] + 1 as [Level]
    from
        MyTable
        inner join
        MyHierarchy on MyTable.ParentId = MyHierarchy.ChildId
    where
        MyTable.ChildId not in (select ChildId from MyHierarchy)
end

Это почти все, что вам нужно. У вас есть запись (ChildId = 6000105), которая ссылается на нескольких родителей. Взяв смещение в сторону более низкого уровня, теперь вы можете использовать функцию row_number() с cte, чтобы получить уникальную взаимосвязь.

with cte as (
    select
        MyHierarchy.*
        ,ROW_NUMBER() OVER(PARTITION BY MyHierarchy.ChildId ORDER BY parent.[Level], MyHierarchy.parentId) as RowNumber
    from
        MyHierarchy
        left join
        MyHierarchy parent on MyHierarchy.ParentId = parent.ChildId
)
select
    *
from
    cte
where
    RowNumber = 1
order by
    ParentId
    ,ChildId

http://sqlfiddle.com/#!18/7089d/3

Ты обалденный. Это прекрасно работает. Спасибо большое.

Sandipan 10.08.2018 20:22

Другие вопросы по теме