存储倒数数据的规范方式 sql

Canonical way to store reciprocal data sql

我有很多相同的实例 Class。现在这些对象可以被 linked 并且这个 link 可以有一个权重。就像在无向图中一样。现在我想在我的 mysql 数据库中存储每两个对象之间的关系。

数据看起来像这样

a ===WEIGHT=== b
a ===WEIGHT=== c
b ===WEIGHT=== a
...

我可以用这种结构创建一个 table:

object1_id | object2_id | weight

但是在搜索两个物体之间的重量时,我不知道哪个是object1,哪个是object2。所以我需要写两个查询。此外,如果我想添加权重并想先检查它是否已经在我的数据库中,我必须编写两个查询以确保它不在其中。

两个查询是:

SELECT weight from tableName where object1_id =  AND object2_id = ;
SELECT weight from tableName where object1_id =  AND object2_id = ;

确保检查这两种可能性,因为我不知道它是如何存储的。

我想有更好的方法来存储这样的数据。可能已经有很多针对这个特定问题的答案,但我不知道这是怎么称呼的,因此很难找到解决方案。

感谢您的建议。

如果数据中只有一条边,那么可以使用:

select t.*
from t
where (object1_id, object2_id) in ( (, ), (, ) );

如果两条边都在 table 中而您任意想要一个,则添加 limit 1.

如果你想强制数据库中只有一条边,你可以在表达式上使用唯一索引:

create unique index unq_t_object1_id_object2_id on
    t( (least(object1_id, object2_id)), (greatest(object1_id, object2_id)) );

您可能还想添加检查约束,以便它们始终按顺序排列:

alter table t add constraint chk_object1_id_object2_id check (object1_id < object2_id);

强制执行这些条件后,您可以将上述查询更改为:

select t.*
from t
where object1_id = least(, ) and
      object2_id = greatest(, );

这样其实优化器更容易优化