如何处理超过2个表的多对多关系?

时间:2011-05-15 01:52:51

标签: mysql many-to-many cross-reference

这就是我现在所处的位置。我有四个表:任务,项目,机会和task_xref。项目和机会表每个都与任务有一对多的关系。我将这些关系存储在task_xref中。对于每个表,模式看起来都是这样的(简化):

task
----
id(pk)
name

project
-------
id(pk)
name
...

opportunity
-----------
id(pk)
name
...

task_xref
---------
task_id(task id)
fkey(other table id)

假设项目和商机中的键不一样(GUID),因此机会无法获取项目的任务等等。这在表面上很有效,一个外部参照表用于维护任务和项目,机会(或将来可能需要任务关系的任何其他表)之间的关系。

我目前的困境是双向性。如果我希望获得单个项目或机会的所有任务,那就没问题了。如果我撤回任务并想知道相关项目或机会的名称我不能。我无法知道相关的fkey是项目还是机会。将来我可能会有其他表与任务关系;虽然我现在有2张桌子,但未来可能会有更多桌子。

以下是我到目前为止所考虑的可能解决方案: 1)每对的单独外部参照表(例如task_project_xref,task_opportunity_xref ......)    缺点:我必须为每个外部参照表运行查询,以查找任务的关系

2)task_xref中的第三列指向父表    缺点:这对我来说似乎是个蠢货

3)以可识别的方式将主键存储在项目中,机会(例如proj1,proj2,proj3,opp1,opp2,opp3),这样我就可以通过查看fkey来判断任务与哪个表相关    缺点:这感觉就像我在项目和机会中使主键变得神奇,给它们带来的意义不仅仅是作为单个记录的标识符(也许我过度思考它)

我的问题是:我还有其他解决方案吗?哪种解决方案比其他解决方案更好/更差?

我试图尽可能保持联接受限并且性能尽可能好。我也不反对在代码中加入数据,如果这有助于简化事情。

我正在使用PHP和MySQL(目前使用MyISAM表,但如果有理由,将使用INNODB)。

2 个答案:

答案 0 :(得分:0)

如果task_xref具有单独的project_id和opportunity_id字段,则SQL连接将更加简洁。这是一种很好的方法,因为查询很简单。此外,只需查看哪些外键不为空,就可以很容易地判断它是什么类型的任务。它也很有效率。在加入任务时,需要两个查询,因为项目和机会无疑会有不同的结构,因此无论如何结果都不能union

答案 1 :(得分:0)

我更喜欢为不同的概念提供单独的外部参照表。这样,从概念到其任务的关系更容易维护,并与其他概念与任务的关系隔离开来。

如果设计中的任何表可能有任务,那么可能赞成所有相关概念的单个外部参照,然后我只需要一个额外的列指出哪种对象是任务的父级。