Вопрос

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

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT 
DAME_ID INT

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

Так:

  1. Может ли кто -нибудь указать мне на статью/веб -страницу, которая обсуждает моделирование таких отношений?
  2. Должен ли ID быть int или какой -то строкой?Нуль в INT указывает на то, что у животного нет родителей в базе данных, но для указания того же самого можно было бы использовать строку со специальными значениями флага.
  3. Возможно, лучше ли это лучше смоделировать через две таблицы?Я имею в виду одну таблицу для животных и отдельная таблица исключительно, указывающая на родство e.г.:

    Животное

    ID INT NOT NULL ПЕРВИЧНЫЙ КЛЮЧ

    Родство

    ID INT NOT NULL ПЕРВИЧНЫЙ КЛЮЧ ВНЕШНИЙ КЛЮЧ

    SIRE_ID INT ПЕРВИЧНЫЙ КЛЮЧ ВНЕШНИЙ КЛЮЧ

    DAME_ID INT ПЕРВИЧНЫЙ КЛЮЧ ВНЕШНИЙ КЛЮЧ

Прошу прощения за вышесказанное:мой SQL заржавел.Надеюсь, это как-то передает то, о чем я думаю.

Это было полезно?

Решение

Что ж, это «нормальное» отношение «один ко многим», и предлагаемый вами метод является классическим для его решения.

Обратите внимание, что две таблицы денормализованы (я не могу точно указать, где находится часть «суперключ-не-хорошо-должно-быть-подмножеством-другого-ключа-fsck-я-забыл», но я почти уверен оно где-то есть);Интуитивная причина заключается в том, что кортеж в первом соответствует не более чем кортежу во втором, поэтому, если у вас нет большого количества животных с нулевыми идентификаторами отца и матери, это не является хорошим решением ни в какой перспективе (оно ухудшает производительность - необходимо соединение - и не снижает требования к объему памяти).

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

Я думаю, что ваш макет с использованием только одной таблицы подойдет.Вы определенно хотите, чтобы SIRE_ID и DAME_ID имели тот же тип данных, что и ID.Вы также хотите объявить их как ВНЕШНИЕ КЛЮЧИ (возможно, чтобы внешний ключ возвращался к той же таблице, и внешний ключ также может быть нулевым).

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT REFERENCES TABLENAME (ID)
DAME_ID INT REFERENCES TABLENAME (ID)

Используя этот макет, вы можете легко найти родительских животных, а также построить дерево потомков для данного животного (для Oracle есть CONNECT BY).

Я задал аналогичный вопрос несколько месяцев назад на веб-сайте MySQL.Я бы порекомендовал вам взглянуть на ответ, который я получил от Питера Броули относительно этого типа отношений: http://forums.mysql.com/read.php?135,187196,187196#msg-187196

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

Альтернативная предлагаемая архитектура (которая будет полностью нормализована) будет выглядеть примерно так:

Стол:животное

Id | Имя | Порода

Стол:родословная

Animal_id | parent_id | Parenttype (сир или дама)

INT — лучший выбор для столбца ID и лучше подходит, если вам нужно использовать последовательность для создания уникальных идентификаторов.

Я не вижу никакой пользы в разбиении дизайна на две таблицы.

Я не разбираюсь в разведении животных, но похоже, что ваш Sire_ID — это отец, а Dame_ID — мать?Без проблем.Одна строка на животное, нулевые sire_ и dame_ID для купленных животных, проблем не предвижу.

[ID],[Sire_ID],[Dame_ID];
0,null,null  (male)
1,null,null  (female)
2,null,null  (female)
3,0,1 (male)
4,0,2 (male)
5,null,null  (female)
6,3,5
7,4,5

и так далее.Скорее всего, вы заполните TreeView или XmlNodeList в цикле while...

While (myAnimal.HasChildren) {
 Animal[] children = GetChildren(Animal.ID)
 for (int x=0; x<children.length; x++) 
  myAnimal.Children.Add(children[x]);
}

В данном случае Animal.Children — это коллекция животных.Следовательно, myAnimal.Children[0].Father вернет myAnimal..Parent[] может быть коллекцией двух своих родителей, что должно работать, пока [0] всегда является одним родителем (отцом), а [1] всегда является другим (матерью).

Сделайте ID Autonumber PK и программно назначьте Sire_ID и Dame_ID, вернув идентификаторы его родителей.Никакие отношения внешнего ключа не обязательны, хотя оба родительских идентификатора могут ссылаться на идентификатор, если вы действительно этого хотите.

Используйте предложение «connect by» в SQL, чтобы указать, какой иерархии следовать.

На самом деле это не связь «один ко многим», если только у животного не может быть много родителей.

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

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

Кажется, вы хотите построить что-то вроде дерева.

А как насчет чего-то вроде?:

 ID          Primary Key,
 Parent_ID   Foreing_Key
 ( data )

Есть некоторая функциональность для выполнения запросов к таблицам, имеющим отношения к самим себе.См. синтаксис Подключиться через: http://www.adp-gmbh.ch/ora/sql/connect_by.html

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top