How to handle many-to-many relationships with more

2019-09-04 12:58发布

问题:

Here is where I am at right now. I have four tables: task, project, opportunity, and task_xref. The project and opportunity tables each have a one-to-many relationship with task. I am storing those relationships in task_xref. The schema looks something like this for each table (simplified):

task
----
id(pk)
name

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

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

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

Assume that the keys in project and opportunity will not be the same (GUID) so an opportunity can't fetch tasks for a project and so on. This works well on the surface, one xref table to maintain the relationships between task and project, opportunity (or any other tables that might need a task relationship in the future).

My current dilemma is of bi-directionality. If I'm looking to get all the tasks for an individual project or opportunity it's no problem. If I'm pulling back a task and want to know the name of the related project or opportunity I can't. I have no way of knowing whether the related fkey is a project or opportunity. In the future I will probably have other tables with task relationships; while I have 2 tables now, there could be many more in the future.

Here are the possible solutions I've thought of so far: 1) separate xref table for each pair (e.g. task_project_xref, task_opportunity_xref...) cons: I have to run a query for each xref table looking for relationships for a task

2) a third column in task_xref to point to the parent table cons: this seems like a kludge to me

3) store the primary keys in project, opportunity in an identifiable way (e.g. proj1, proj2, proj3, opp1, opp2, opp3) so I can tell which table a task relates to by looking at the fkey cons: this feels like I'm making the primary keys in projects and opportunities magical, imbuing them with more meaning than just being an identifier to a single record (maybe I'm over-thinking it)

My question then is this: Are there other solutions I am overlooking? Which solution is better/worse than the others?

I am trying to keep joins limited if possible and performance as good as possible. I am also not opposed to joining data in code if that will help simplify things.

I am using PHP and MySQL (MyISAM tables presently, but will use INNODB if there is a reason to do so).

回答1:

I do prefer to have a separate xref table for the different concepts. This way, the relationship from a concept to its tasks is easier to maintain and isolated from the other concept's relationships to tasks.

I'd maybe favor a single xref for all related concepts if any table in your design could have tasks, and then I'd just have an extra column to indicate which kind of object is the parent of the tasks.



回答2:

Your SQL joins will be neater if task_xref has separate project_id and opportunity_id fields. It's a good way of doing it, because queries are straightforward. Also, it's simple to tell what type of task it is, by simply seeing which of the foreign keys is not null. It's also efficient. When joining with tasks, two queries are needed, since project and opportunities will no doubt have different structures, so the results can't be union'd anyway.