Ищете способ хранения структуры родитель-ребенок-внук - PullRequest
4 голосов
/ 25 августа 2011

Мне нужно хранить структуру, в которой у N родителей будет от 1 до N детей, а у каждого ребенка будет от 1 до N детей.Я хотел бы хранить это в БД способом, который является относительно производительным и легко расширяемым без необходимости изменения схемы БД.

Каждый родитель должен быть уникальным, и у N родителей может быть один и тот же ребенок.Однако у этого ребенка могут быть разные дети в зависимости от родителя.(ясно, как грязь?)

Может быть проще описать это, поскольку у родителя А может быть ребенок мужского пола, который имеет определенные признаки (каштановые волосы, карие глаза).у parentb также есть ребенок мужского пола, но у этого ребенка светлые волосы и голубые глаза.Мне нужно хранить каждого из этих детей (мужского и женского пола) и каждый атрибут (цвет волос и глаз) в нормализованном порядке и связывать их таким образом, чтобы при запросе паренты я получал все их дочерние элементы и атрибуты этих детей.

Я немного поработал с древовидными структурами и иерархическими структурами в SQL, но мне трудно осмыслить этот конкретный сценарий таким образом, чтобы он отвечал моим требованиям к производительности и расширяемости.Дочерние и связанные атрибуты будут добавляться через регулярные (если не часто) интервалы.Заранее спасибо.Я знаю, что потребуется разъяснение.

Дополнительное разъяснение

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

CarA и CarB имеют рулевое колесо, двигатели и шины.На руле CarA есть радиоуправление.Руль у CarB нет.CarA имеет шестицилиндровый двигатель, а CarB - восьмицилиндровый.Мне нужно смоделировать отношения между каждой машиной и каждой функцией с помощью атрибута этой функции.Я вообще помогаю?-rb

Ответы [ 4 ]

3 голосов
/ 25 августа 2011

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

  • стол для родителей
  • таблица для детей (если у них всегда ровно два родителя, родители могут быть полями, в противном случае вам также понадобится таблица для отношений)
  • таблица для атрибутов и другая для отношения «многие ко многим» между этим и потомками [или сохраните их в таблице потомков - см. Комментарий к DForck42 ниже]

деревья необходимы там, где узлы на разных уровнях - это «одно и то же». но они не очень подходят для SQL, поэтому я бы не стал пытаться использовать их там, где они не нужны.


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

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

поэтому у вас будет родительская таблица с идентификаторами. тогда у вас может быть дочерняя таблица для "сайтов администратора". каждая строка этой дочерней таблицы будет ссылаться на родителя через идентификатор и содержать URL, CSS и т. д. в качестве столбцов. другой дочерний тип, такой как «страница конфигурации базы данных», будет находиться в другой таблице с другим набором атрибутов.

если у вас есть общие атрибуты, вы можете либо повторить их в каждой таблице, либо иметь таблицу «суперкласса».

подобные решения могут стать довольно сложными, и я бы предложил задать другой вопрос, когда у вас будет более четкое объяснение того, что вы хотите. здесь есть хорошее объяснение параметров - http://www.sqlalchemy.org/docs/orm/inheritance.html (игнорируйте части, относящиеся к SQLAlchemy, и просто посмотрите, как они по-разному используют таблицы для моделирования наследования).

1 голос
/ 25 августа 2011

Что не так со следующим подходом:

create Table Persons    {
  PersonID int Primary Key,
  Name  varchar(100),
  MotherID int {Foreign Key},
  FatherID int {Foreign Key}
}

create Table Attributes
{
    PersonID int {Foreign Key},
    AttributeName varchar(10),
    AttributeValue varchar(10)
}

Вы получите все атрибуты для данного лица детей по:

Select
      Persons.Name,
      Attributes.AttributeName,
      Attributes.AttributeValue
From
      Persons
Left Join
      Atttributes
On
     Persons.PersonID = Attributes.PersonID  
Where
     MotherID = @PersonID or FatherID = @PersonID
1 голос
/ 25 августа 2011

Ну, вот другой подход. Вам нужны только две таблицы. Первый - это место, где вы храните все свои «объекты» (какими бы они ни были), составляющие вашу иерархию:

ObjectID | ObjectName | ...

Вторая таблица отношений:

RelID | ParentID | ChildID

Таблица отношений может включать в себя ограничение, гарантирующее, что ни один объект не является дочерним по отношению к более чем одному родительскому элементу, что дает вам целостность практически бесплатно.

Теперь обход таблицы (таблиц) для извлечения иерархии может быть сложным, но это можно сделать с помощью относительно простого хранимого процесса. Есть два улова. Во-первых, все ваши объекты должны иметь одну и ту же таблицу и, следовательно, одинаковые уникальные идентификаторы (в идеале). Во-вторых, сколько уровней рекурсии поддерживает ваша БД. По моему опыту, например, 32 уровня, поддерживаемые SQL Server, были более чем достаточными. Однако выполнение обхода в коде, а не в БД может снизить производительность.

Есть и другие способы подойти к этому. Если вы Google для database hierarchical data, вы найдете несколько, в том числе формальный документ CS или два.

Я использовал этот метод в прошлом, и я считаю его достаточно простым и эффективным.

1 голос
/ 25 августа 2011

Как я читаю ваш вопрос, вам нужно всего пять таблиц.

 -> Parent
    ParentId, Col1, Col2, Col3

 -> Child
    ChildId, Col1, Col2, Col3

 -> Grandchild
    GrandchildId, Col1, Col2, Col3

 -> ParentToChild
    ParentId, ChildId

 -> ChildToGrandchild
    ChildId, GrandchildId

Это хранит все отношения, и вы должны были бы установить ограничения для логики, которую вы хотите;в этой реализации отношения N к N возможны для (Parent, Child) и (Child, Grandchild).

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