Pregunta

¿Cómo se podría estructurar una tabla para una entidad que puede tener una relación de uno a muchos consigo misma? Específicamente, estoy trabajando en una aplicación para rastrear la cría de animales. Cada animal tiene una identificación; También tiene una identificación de sire y una identificación de dama. Por lo tanto, es posible tener uno a muchos del padre o la madre a su descendencia. Me inclinaría por algo como esto:

ID INT NOT NULL PRIMARY KEY
SIRE_ID INT 
DAME_ID INT

y registre un valor nulo para aquellos animales que fueron comprados y agregados al ganado y una identificación en la tabla para el resto.

Entonces:

  1. ¿Alguien puede señalarme un artículo / página web que discute modelando este tipo de relación?
  2. ¿Debería la identificación ser un INT o algún tipo de cuerda? Un NULL en el INT sería indicar que el animal no tiene padres en la base de datos pero una cadena con valores de bandera especiales podrían ser solía indicar lo mismo.
  3. ¿Sería esto mejor modelado? a través de dos mesas? Me refiero a una mesa para los animales y un separado tabla que indica únicamente parentesco e. g .:

    Animal

    ID INT NO CLAVE PRIMARIA NULA

    Parentesco

    ID INT NO NULO CLAVE PRIMARIA CLAVE EXTRANJERA

    SIRE_ID INT CLAVE PRIMARIA CLAVE EXTRANJERA

    DAME_ID INT CLAVE PRIMARIA CLAVE EXTRANJERA

Pido disculpas por lo anterior: mi SQL está oxidado. Espero que de alguna manera transmita lo que estoy pensando.

¿Fue útil?

Solución

Bueno, esta es una "normal" relación uno a muchos y el método que sugiere es el clásico para resolverlo.

Tenga en cuenta que dos tablas están desnormalizadas (no puedo señalar exactamente dónde está la parte superkey-is-not-well-should-be-subset-of-other-key-fsck-I-olvido, pero yo ' Estoy bastante seguro de que está allí en alguna parte); La razón intuitiva es que una tupla en la primera coincide como máximo con una tupla en la segunda, por lo que, a menos que tenga muchos animales con identificaciones nulas de padre e hija, no es una buena solución en ninguna perspectiva (empeora el rendimiento, la necesidad una combinación, y no reduce los requisitos de almacenamiento).

Otros consejos

Creo que su diseño usando solo una tabla está bien. Definitivamente desea mantener SIRE_ID y DAME_ID en el mismo tipo de datos que ID. También desea declararlos como CLAVES EXTRANJERAS (es posible que un punto de clave externa vuelva a la misma tabla, y una clave externa también puede ser nula).

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

Usando este diseño, puede buscar fácilmente los animales padres, y también podría construir un árbol de descendencia para un animal determinado (para Oracle hay CONECTAR POR)

Hice una pregunta similar hace varios meses en el sitio web MySQL. Recomiendo que eche un vistazo a la respuesta que recibí de Peter Brawley con respecto a este tipo de relación: http : //forums.mysql.com/read.php? 135,187196,187196 # msg-187196

Si desea investigar más sobre el tema, le recomendaría que consulte las jerarquías de árboles en Wikipedia.

Una arquitectura alternativa sugerida (que estaría completamente normalizada) sería similar a la siguiente:

Tabla: animal

ID | Nombre | Raza

Tabla: pedigrí

animal_id | parent_id | parentType (ya sea padre o madre)

INT es la mejor opción para la columna de ID y más adecuada si usa una secuencia para generar ID únicos.

No veo ningún beneficio en dividir el diseño en dos tablas.

No sé acerca de la cría de animales, pero parece que su Sire_ID es el padre y Dame_ID es la madre. No hay problema. Una fila por animal, nulo sire_ y dame_ID para los animales comprados, no preveo ningún problema.

[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

y así sucesivamente. Es probable que complete una TreeView o XmlNodeList en un ciclo while ...

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

En este caso, Animal.Children es una colección de animales. Por lo tanto, myAnimal.Children [0] .Father devolvería myAnimal. .Parent [] podría ser una colección de sus dos padres, que debería funcionar siempre que [0] sea siempre uno de los padres (padre) y [1] sea siempre el otro (madre).

Convierta la ID en un PK de Autonumeración y asigne Sire_ID y Dame_ID programáticamente mediante la devolución de las ID de sus padres. No deberían ser necesarias relaciones de clave externa, aunque ambas ID principales podrían hacer referencia a ID si realmente lo desea.

Utilice el " conectar por " cláusula con SQL para indicarle qué jerarquía seguir.

No es realmente una relación de uno a muchos, a menos que un animal pueda tener muchos padres.

Lo dejaría como una sola tabla con la ID de clave única para el animal, un campo int para cada uno de los padres y probablemente un campo de texto para usar para notas generales sobre el animal, como dónde se compró si es el caso.

Creo que, dado que está claro que un animal solo tiene un padre y una madre, usar una sola mesa tendría más sentido. Mi preferencia es usar int o bigint como identificador de fila, con un valor nulo que significa que no hay relación. Probablemente, entonces, usaría algún otro método para identificar de manera única a los animales para que no terminen en la tabla dos veces y también creen un índice único en esa columna.

Parece que quieres construir algo como un árbol.

¿Qué pasa con algo así ?:

 ID          Primary Key,
 Parent_ID   Foreing_Key
 ( data )

Hay algunas funcionalidades para hacer consultas en tablas con relaciones consigo mismas. Consulte la sintaxis de Connect By : http: // www.adp-gmbh.ch/ora/sql/connect_by.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top