2008-10-01 5 views
4

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

ID INT NOT NULL PRIMARY KEY 
SIRE_ID INT 
DAME_ID INT 

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

Итак:

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

    животных

    ID INT NOT NULL, PRIMARY KEY

    Сходство

    ID INT NOT NULL, PRIMARY KEY FOREIGN KEY

    SIRE_ID INT PRIMARY KEY FOREIGN KEY

    DAME_ID INT ПЕРВИЧНЫЙ КЛЮЧЕВОЙ ИНОСТРАННЫЙ КЛЮЧ

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

+0

Если вы используете Oracle, ищите информацию о connect_path. это расширение для sql, которое позволяет создавать «иерархические запросы», извлекать в 1 запросе всех потомков или предков, которым нравится отношение, которое вы хотите. – helios 2008-10-01 22:15:05

+0

@helios, Спасибо за это. – 2008-10-01 22:21:07

ответ

5

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

Обратите внимание, что две таблицы денормализованы (я не могу указать точно, где находится элемент superkey-is-not-well-should-be-subset-of-other-key-fsck-I-forget, но я Я уверен, что он где-то там); интуитивная причина заключается в том, что кортеж в первом соответствует, по крайней мере, кортежу во втором, поэтому, если у вас нет большого количества животных с нулевым типом и идентификаторами дам, это нехорошее решение в любой перспективе (это ухудшает производительность - нужно соединение - и не снижает требования к хранению).

+0

Большое спасибо - это именно то, чего я надеялся получить. – 2008-10-01 22:11:09

+0

нормализованные формы, по крайней мере 3 первых из них, говорят об использовании правильной таблицы и правильном pk. a) избегая слияния поднабора столбцов со своей собственной функциональной зависимостью в большую таблицу (2NF); b) избегая транзитивных отношений с pk. обратите внимание, что здесь не так, так что это идеально. – helios 2008-10-01 22:13:04

+0

Я уверен, что это считается вырожденным случаем транзитивности. – millenomi 2008-10-01 22:25:05

1

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

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

+0

Преимущество разделения дизайна на две таблицы - это просто нормализовать структуру данных. Обычно это позволяет оптимально использовать функциональные возможности SQL. – 2008-10-03 11:23:20

3

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

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

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

Таблица: животное

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

Таблица: родословная

animal_id | parent_id | parentType (либо sire или dame)

0

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

0

Это не совсем одно отношение, если у животного не может быть много родителей.

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

0

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

3

Я думаю, что ваш макет, используя только одну таблицу в порядке. Вы определенно хотите сохранить SIRE_ID и DAME_ID в том же типе данных, что и ID. Вы также хотите объявить их как FOREIGN KEYs (возможно, что внешняя ключевая точка возвращается к одной и той же таблице, а внешний ключ также может быть нулевым).

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

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

0

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

А что-то вроде ?:

ID   Primary Key, 
Parent_ID Foreing_Key 
(data) 

Есть некоторые функциональные возможности для выполнения querys в таблицах с отношением к себе. Смотрите синтаксис Connect By: http://www.adp-gmbh.ch/ora/sql/connect_by.html

1

Я не знаю, о разведении животных, но это звучит как ваши Sire_ID отец и Dame_ матери? Нет проблем. Одна строка для каждого животного, null 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. ,Родитель [] может быть сборником двух его родителей, который должен работать до тех пор, пока [0] всегда один родитель (отец), а [1] всегда другой (мать).

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