Создание оператора cte для обхода дерева, созданного с помощью таблицы мостов - PullRequest
0 голосов
/ 05 мая 2018

Я предвосхищу это, сказав, что я совершенно новичок в утверждениях cte.

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

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

Теперь я пытаюсь создать оператор cte, который делает то же самое. Содержание потомства, заказанного ниже родителей, не так уж и сложно

Итак, я создал образец базы данных и другие материалы для описания моей проблемы:

Эта диаграмма наглядно показывает, каковы отношения: 1012 * схема *

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

    1 : Audio
        2 : Speaker
        3 : Microphone
        4 : Mic Pack
            3 : Microphone
            5 : Di
                6 : Passive Di
                    11 : Rapco Di
                    13 : Dbx Di
    7 : Lighting
        9 : Safety
            12 : Small Safety
    8 : Rigging
        10 : Light Rigging
            9 : Safety
                12 : Small Safety

Пример таблицы: CREATE TABLE items (id INTEGER, name TEXT, ПЕРВИЧНЫЙ КЛЮЧ (id));

CREATE TABLE `linker` ( `parent` INTEGER, `child` INTEGER, PRIMARY KEY(`parent`,`child`) );

Insert Into items(id, name) Values(1, 'Audio');
Insert Into items(id, name) Values(2, 'Speaker');
Insert Into items(id, name) Values(3, 'Microphone');
Insert Into items(id, name) Values(4, 'Mic Pack');
Insert Into items(id, name) Values(5, 'Di');
Insert Into items(id, name) Values(6, 'Passive Di');
Insert Into items(id, name) Values(7, 'Lighting');
Insert Into items(id, name) Values(8, 'Rigging');
Insert Into items(id, name) Values(9, 'Safety');
Insert Into items(id, name) Values(10, 'Lighting Rigging');
Insert Into items(id, name) Values(11, 'Rapco Di');
Insert Into items(id, name) Values(12, 'Small Safety');
Insert Into items(id, name) Values(13, 'Dbx Di');

Insert Into linker(parent, child) Values(1, 2);
Insert Into linker(parent, child) Values(1, 4);
Insert Into linker(parent, child) Values(1, 3);
Insert Into linker(parent, child) Values(4, 3);
Insert Into linker(parent, child) Values(4, 5);
Insert Into linker(parent, child) Values(5, 6);
Insert Into linker(parent, child) Values(6, 11);
Insert Into linker(parent, child) Values(6, 13);
Insert Into linker(parent, child) Values(7, 9);
Insert Into linker(parent, child) Values(9, 12);
Insert Into linker(parent, child) Values(8, 10);
Insert Into linker(parent, child) Values(10, 9);

Это тот самый компьютер, который я придумал, который, как мне кажется, был самым близким, но, вероятно, он все еще довольно далек:

  with cte As
    (
    Select 
        id,
   name,
   0 as level,
   Cast(name as varchar(255) as sort
    From items i
    Left outer Join
    linker li
    On i.id = li.child
    And li.parent is Null

    Union All

    Select 
        id,
        name,
        cte.level + 1,

        Cast(cte.sort + '.' + i.name As Varchar(255)) as sort
    From cte
    Left Outer Join linker li
    on li.child = cte.id
    Inner Join items i
    On li.parent = i.id
    )

Select 
    id,
    name,
    level,

    sort
From cte
Order By Sort;

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

Редактировать: Вероятно, стоит отметить, что результаты не должны быть в порядке. Я планирую создать поле пути предка в операторе cte и использовать этот патб для заполнения моего дерева.

Редактировать: упс, я скопировал и вставил неправильный бит cte-кода. Я нахожусь на мобильном телефоне, поэтому я сделал все возможное, чтобы изменить его на то, что я делал на своем рабочем столе. Как только у меня появится возможность, я дважды проверю заявление cte против моих записей.

1 Ответ

0 голосов
/ 06 мая 2018

Хорошо, похоже, мой мозг просто нуждался в отдыхе. Я нашел решение моей проблемы с гораздо меньшим разочарованием, чем вчера.

Мое утверждение было:

with cte As(
    Select 
       id,
       name, 
       li.parent,
       li.child,
       Cast(name as Varchar(255)) as ancestory
    From items i
    Left Outer Join linker li
    On i.id = li.child
    Where li.parent is null

    Union All

    Select 
        i.id,
        i.name,
        li.parent,
        li.child,
        Cast(cte.ancestory || "." || i.name as Varchar(100)) as ancestory
    From cte
    Left join linker li
    On cte.id = li.parent
    Inner Join items i
    On li.child = i.id

        )
select * from cte

Результаты возвращаются как:

  id    name        parent    child    ancestory
   1    Audio                          Audio
   7    Lighting                       Lighting
   8    Rigging                        Rigging
   2    Speaker       1          2     Audio.Speaker
   3    Microphone    1          3     Audio.Microphone
   4    Mic Pack      1          4     Audio.Mic Pack
   9    Safety        7          9     Lighting.Safety
  10    Lighting      8         10     Rigging.Lighting Rigging
         Rigging
   3    Microphone    4          3     Audio.Mic Pack.Microphone
   5    Di            4          5     Audio.Mic Pack.Di
  12    Small         9         12     Lighting.Safety.Small Safety
         Safety
   9    Safety       10          9     Rigging.Lighting Rigging.Safety
   6    Passive Di    5          6     Audio.Mic Pack.Di.Passive Di
  12    Small Safety  9         12     Rigging.Lighting Rigging.Safety.Small Safety
  11    Rapco Di      6         11     Audio.Mic Pack.Di.Passive Di.Rapco Di
  13    Dbx Di        6         13     Audio.Mic Pack.Di.Passive Di.Dbx Di
...