SQL查询中的双向关系

SQL查询中的双向关系,sql,database-design,relational-database,Sql,Database Design,Relational Database,我有一个用于跟踪零件的小数据库。在本例中,表格如下所示: SELECT PartNumber FROM tblPartRelationships WHERE RelationshipID ANY (SELECT RelationshipID FROM tblPartRelationships WHERE PartNumber = 'XYZ123') PartID(主键),int 零件号,Va

我有一个用于跟踪零件的小数据库。在本例中,表格如下所示:

SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
                          FROM tblPartRelationships
                          WHERE PartNumber = 'XYZ123')
PartID(主键),int
零件号,Varchar(50),唯一性
说明,Varchar(255)

我有一个要求来定义某些部分被分类为彼此相似。 为此,我设置了第二个表,如下所示:

SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
                          FROM tblPartRelationships
                          WHERE PartNumber = 'XYZ123')
PartID,(主键),int
第二方,(PK),int
相似性的原因,Varchar(255)

然后在两个表之间建立了多对多关系

当我需要报告被认为相似的零件时,问题就出现了,因为这种关系是双向的,即如果零件XYZ123与ABC678相似,则ABC678被认为与XYZ123相似。因此,如果我想列出与给定零件相似的所有零件,我要么需要确保在两个方向上建立关系(这是不好的,因为数据重复),要么需要有两个查询在两个方向上查看表。我觉得这两种解决方案都不对

那么,应该如何处理这个问题呢?这可以单独用SQL来解决,还是我的设计需要改变以适应业务需求

考虑以下零件XYZ123、ABC123、ABC234、ABC345、ABC456和EFG456,这些零件已输入上述现有结构中。您可能会得到如下数据(忽略与此无关的原因字段):

第三方第二方
XYZ123,ABC123
XYZ123,ABC234
XYZ123,ABC345
XYZ123,ABC456
EFG456,XYZ123

我的用户想知道“哪些部件与XYZ123相似”。这可以使用如下查询完成:

SELECT SecondPartID
FROM tblRelatedParts
WHERE PartID = 'XYZ123'
尽管如此,问题在于它不会选择与XYZ123相关的零件EFG456,尽管这些零件是以相反的方式输入的。这是可行的,这取决于用户当前使用的部件以及部件之间的关系始终是双向的

但我的问题是,我现在需要检查,当用户在两个部分之间建立关系时,它在另一个方向上并不存在

@Goran

我已经用你的建议做了一些初步测试,这就是我打算用你的建议来解决这个问题的方法

上面列出的数据输入到新表中(请注意,我已将partID更改为part number以使示例更清晰;但问题的语义没有更改)

该表如下所示:

SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
                          FROM tblPartRelationships
                          WHERE PartNumber = 'XYZ123')
关系ID零件号
1,XYZ123
1,ABC123
2,XYZ123
2,ABC234
3,XYZ123
3,ABC345
4,XYZ123
4,ABC456
5,EFG456
5,XYZ123

然后,我可以使用如下查询检索类似零件的列表:

SELECT PartNumber
FROM tblPartRelationships
WHERE RelationshipID ANY (SELECT RelationshipID
                          FROM tblPartRelationships
                          WHERE PartNumber = 'XYZ123')

我将进行更多的测试,如果有效,我将反馈并接受答案。

添加
检查
约束,例如

CHECK (PartID < SecondPartID);
检查(PartID
我通过设置关系表来处理这个问题

零件表:

第三方(主键),整数

零件号,Varchar(50),唯一

说明,Varchar(255)

PartRelationship表:

关系ID(FK),国际

第三方(FK),国际

关系表:

关系ID(主键),int

现在,类似的部分只需添加到关系表中:

关系ID,PartId

1,1

1,2

无论何时添加relationshipId=1的其他零件,都会认为它与relationshipId=1的任何零件相似

用于添加关系的可能API解决方案:

  • 为每个相似零件列表创建新关系。让客户端在需要时加载、更改和更新整个列表
  • 检索类似对象的关系。按某些条件筛选列表,以便只保留一个条件,或让客户从现有关系中进行选择。根据需要创建、删除PartRelationship记录
  • 从关系表中检索关系列表。让客户机指定部件和关系。根据需要创建、删除PartRelationship记录

我知道这很旧,但为什么不使用原始模式执行此查询?更少的表和行

SELECT SecondPartID
FROM tblRelatedParts
WHERE PartID = 'XYZ123' 
UNION
SELECT PartID
FROM tblRelatedParts
WHERE SecondPartID = 'XYZ123'

我正在处理一个类似的问题,研究这两种方法,想知道为什么您认为使用关系表的模式更好。似乎原始问题仍然存在,即您仍然需要从两个方向管理它们之间的关系。

每个相似性有两行如何。例如,如果在关系表中有类似的对象A、B

A B
B A
我知道您将使关系数据加倍,但它们是整数,因此不会过度破坏数据库。相反,你有一些收获:

  • 你不会使用工会。在任何数据库管理系统中,联合都是致命的。尤其是当您有订单或分组时
  • 您可以实现更具体的关系:a与b相关,但b与a无关。例如,约翰可以代替戴夫,但戴夫不能代替约翰

+1,尽管您可能希望添加一个额外的表以满足
原因相似性
字段的要求,该字段可能仅限于特定的对(而不适用于关系中的所有部分)。@MarkBannister很好。我不确定所有的要求是什么,但这应该让OP指向正确的方向。如果有任何需要,我会更新我的答案@本杰明?+1,这看起来是一个有效的解决方案。我会做一些测试,让你知道这是怎么回事。只有一件事