Tengo una pequeña base de datos que se usa para rastrear partes. por el bien de este ejemplo, la tabla es el siguiente:Relaciones bidireccionales en consultas SQL
Idpart (PK), int
PartNumber, varchar (50), único
Descripción, VARCHAR (255)
Tengo un requisito para definir que ciertas partes se clasifican como similares entre sí. Para ello he fijado una segunda tabla que tiene este aspecto:
Idpart, (PK), int
SecondPartID, (PK), int
ReasonForSimilarity, VARCHAR (255)
Luego se ha configurado una relación de muchos a muchos entre las dos tablas.
El problema viene cuando tengo que informar sobre las partes que se consideran similares porque la relación es bidireccional I.E. si parte XYZ123 es similar a ABC678 entonces ABC678 se considera que es similar a XYZ123. Entonces, si quisiera enumerar todas las partes que son similares a una parte dada, o bien debo asegurarme de que la relación esté configurada en ambas direcciones (lo cual es malo porque los datos están duplicados) o necesito tener 2 consultas que miren la tabla en ambas direcciones . Ninguna de estas soluciones me parece bien.
Entonces, ¿cómo se debe abordar este problema? ¿Se puede resolver esto solo con SQL o mi diseño debe cambiar para adaptarse a los requisitos del negocio?
Considere las siguientes partes XYZ123, ABC123, ABC234, ABC345, ABC456 & EFG456 que se han ingresado en la estructura existente ingresada anteriormente. Usted podría terminar con los datos que tiene este aspecto (omitiendo el campo de la razón, que es irrelevante en este punto):
Idpart, SecondPartID
XYZ123, ABC123
XYZ123, ABC234
XYZ123, ABC345
XYZ123, ABC456
EFG456, XYZ123
Mi usuario quiere saber "¿Qué partes son similares a XYZ123". Esto podría hacerse mediante una consulta de este modo:
SELECT SecondPartID
FROM tblRelatedParts
WHERE PartID = 'XYZ123'
El problema con esto es sin embargo que no se le fuera parte EFG456 que se relaciona con XYZ123 a pesar de que las partes se han introducido al revés. Es posible que esto ocurra dependiendo de la parte con la que el usuario esté trabajando actualmente y la relación entre las partes será siempre sea bidireccional.
El problema que tengo con esto es que ahora necesito comprobar que cuando un usuario establece una relación entre dos partes, no existe ya en la otra dirección.
@Goran
me han hecho algunas pruebas iniciales usando su sugerencia y así es como tengo la intención de abordar el problema con su sugerencia.
Los datos mencionados anteriormente se introducen en la nueva tabla (Tenga en cuenta que he cambiado el Idpart al número de pieza para hacer el ejemplo más claro; la semántica de mi problema no han cambiado sin embargo)
se vería la tabla como esta:
RelationshipID, PartNumber
1, XYZ123
1, ABC123
2, XYZ123
2, ABC234
3, XYZ123
3, ABC345
4, XYZ123
4, ABC456
5, EFG456
5, XYZ123
puedo entonces recuperar una lista de partes similares utilizando una consulta como esta:
SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
FROM tblPartRelationships
WHERE PartNumber = 'XYZ123')
voy a llevar a cabo más pruebas y si esto funciona me retroalimentación y aceptar la respuesta.
+1, aunque es posible que desee agregar una tabla adicional para el campo 'ReasonForSimilarity', que probablemente esté restringido a pares específicos (en lugar de aplicable a todas las partes de una relación). –
@MarkBannister Buen punto. No estoy seguro de cuáles son todos los requisitos, pero esto debería hacer que OP apunte en la dirección correcta. Si hay alguna necesidad, actualizaré mi respuesta. @¿Benjamín? – Goran
+ 1, esto parece una solución válida. Haré algunas pruebas y te dejaré saber cómo va esto. Solo una cosa con respecto a la relación Id; ¿Cómo se genera y mantiene esto? presumiblemente, tendré que asegurarme de que se usa la relación correcta al establecer un enlace entre las partes para garantizar que esto funcione. @MarkBannister Ya tengo una tabla separada para ReasonForSimilarity, pero la excluí porque no afecta lo que quiero. –