如何实现3+记录之间的交叉引用?

时间:2013-05-26 18:22:33

标签: mysql

我有一个具有这种结构的表

(int)id | (text)title | (text)description | (int)related

和一个将表连接到自身的查询

SELECT t1.*, t2.title as relatedTitle
FROM mytable t1 LEFT JOIN mytable t2 ON t2.related=t1.id

在这样的SELECT列表中生成

title:您好,description:非正式的问候,see also:您好

当新记录存储到表中时,只能引用另一个记录

one-way reference

我尝试实现的是交叉引用

cross-reference

可以是2-5个对象

multi cross-reference

所有对象都应在每种组合中交叉引用。我想要这个功能:如果设置了related,脚本应该在相关记录中自动创建交叉引用。如果删除了记录,则脚本应更新相关记录中的引用。

对于3个以上交叉引用的记录,我正在考虑这个连接表

(int)id | (int)related

但是对于5个交叉引用的对象,它将是20条记录。我也可以创建一个列的表

(varchar)relatedList

但是如何创建左连接以及如何删除此结构中的关系?或者我应该尝试其他方法,如触发器,视图或临时表?我想避免冗余,尽量保持简单,只是无法解决这个问题。

3 个答案:

答案 0 :(得分:1)

如果您的组通常大于2,那么您应该创建一个组列表 - 如果A连接到B和C,则它创建组A,B,C。

因此,只要插入关系,就会检查相关项是否已在组中。如果已设置,则“新”相关条目也在该组中。

如果没有,您刚刚创建了一个包含这两个项目的新组。

因此,如果您的示例“Hi”是单独的,并且“Ho”连接到“Hi”,则两者都形成一个新组。 当“Ahoi”也与“Hi”连接时,只需要从Hi中复制group_id。

编辑:根据评论要求选择:

结构:

table groups: group_id int not null primary key auto_increment, created_tmstmp timestamp
table items: item_id int, group_id int default null

选择:

select * from items i1 
inner join items i2 on i2.item_id != i1.item_id 
      and i2.group_id = i1.group_id 
where i1.id = <given item>.

关系的插入可以连接到其中一个项目的插入,这取决于线程所有者的场景。如果它是两个条目的新关系,则插入一个新组。

其他问题是:只有一个项目的项目?否则,需要item_group表将项目连接到多个组。

没有加入字符串,对不起有可能被如此残忍地理解。 ; - )

答案 1 :(得分:0)

选择这个:

(int)id | (int)related

这是一种非常常见的方法。

如果使用列表方法,则SQL查询将非常复杂。

通常,SQL引擎非常擅长针对具有大量行的表优化查询,因此在最合理的硬件上,您不必担心此类表中的数百万行。 (当然,取决于你将要使用它。)

要为非定向边建模,请始终在id列中插入最低的ID(您可以添加CHECK约束来强制执行此操作)。通过这样做,你将消除一半的元组。

如果由于想要对完整图形进行建模而遇到性能问题,请考虑仅使用上表中的“邻居”连接,计算图形的完成情况并将其插入包含所有项目分区的表中,每个完整子图的分区:

(int)partition | (int)id

让我们来看一个例子。给定项目(1 ... 8)和边缘(1,2),(1,3),(4,3),(6,5),(6,7) - 不包括所需的边缘完成图表,你得到

(int)id | (int)related
      1 |            2
      1 |            3
      3 |            4
      5 |            6
      6 |            7

(并且没有项目8的记录。)

然后在分区表中:

(int)partition | (int)id
             1 |       1
             1 |       2
             1 |       3
             1 |       4
             2 |       5
             2 |       6
             2 |       7
             3 |       8

要检查某个项目是否与另一个项目相关,只会在分区表上进行自联接,但更改图表需要同时操作这两个表格。

答案 2 :(得分:0)

正如mzedeler所说,通常使用连接表实现多对多关系。请考虑使用单独的id列,以便获得

Id,rel1,rel2

像hibernate这样的框架会知道该怎么做。考虑到您正在谈论传递和对称关系这一事实,这更有意义。因此,对于4个相关项目,如果您的脚本执行一些基本推理,则3个条目就足够了。当然,如果连接条目被删除,您需要填补给定关系链中的空白。