几个多对多关系到一张表

Posted

技术标签:

【中文标题】几个多对多关系到一张表【英文标题】:Several many-to-many relationships to one table 【发布时间】:2015-07-13 15:08:00 【问题描述】:

我的数据库有几个类别,我想将用户创作的文本“注释”附加到这些类别中。例如,一个名为jobs 的高级表中的条目可能有一些用户写的关于它的注释,但sub_projects 中的一个较低级别的条目也可能如此。由于这些笔记都是相同的格式,我想知道我是否可以通过只有一个笔记表而不是像job_notesproject_notes这样的一系列表来简化事情,然后使用多个多对多关系以一次将其链接到其他几个表。

如果这不是从一开始就存在严重缺陷的想法(如果是,请告诉我!),我想知道最好的方法是什么。在我看来,我可以通过两种方式做到这一点:

    为每个较大的类别(例如 job_notes_mappingproject_notes_mapping)提供多对多连接表,并单独管理 MtM 关系

    将单个联结表链接到 table_type 的枚举或单独的表,它指定 MtM 关系映射到哪个表:

    +-------------+-------------+---------------+
    | note_id     | table_id    | table_type_id |
    +-------------+-------------+---------------+ 
    |           1 |           1 | jobs          |
    |           2 |           2 | jobs          |
    |           3 |           1 | project       |
    |           4 |           2 | subproject    |
    | ........... | ........... | ........      |
    +-------------+-------------+---------------+
    

如果这些想法中的任何一个是完全可怕的想法,请原谅我,但我认为这至少在概念上可能是一个有趣的问题。

【问题讨论】:

【参考方案1】:

IMO 理想的方式是拥有工作、项目和子项目的超类型 - 我们称之为活动 - 您可以在其上定义任何常见的事实类型。

例如(我假设工作、项目和子项目形成一个包含层次结构):

activities (activity PK, activity_name, begin_date, ...)
jobs (job_activity PK/FK, ...)
projects (project_activity PK/FK, job_activity FK, ...)
subprojects (subproject_activity PK/FK, project_activity FK, ...)

不幸的是,大多数数据库模式为每个表定义了唯一的自动递增标识符,这使得在加载数据后实现超类型变得非常困难。 PostgreSQL 允许重用序列,这很好,其他一些 DBMS(如 mysql)根本无法做到这一点。

我的第二个选择是您的选项 1,因为它允许定义外键约束。我根本不喜欢选项 2。

【讨论】:

如果有人想知道我的示例中的列命名约定,它是 role_domain 而不是 table_id。 不幸的是,第二次看这个答案实际上不是我想要的。由于活动将通过外键引用,因此不再是多对多关系 - 您只能为一项工作拥有一个活动条目。就我的 Notes 而言,我希望有多个注释来描述一个工作/项目/子项目。 我的目标是超类型作业、项目和子项目,以便可以使用活动和注释之间的多对多映射,而不是每个级别的单独映射。我没有建议活动来代替笔记。 所以你描述的是一个系统,它去job->activity<-activity_note_mapping->notes?你能描述一下你创建条目的顺序,以及它与你描述的超类型问题的关系吗? 在我的建议中,每个工作(以及项目和子项目)都是一个活动,因此您可以直接将工作加入到 activity_note_mapping 中。如果作业、项目和子项目的 id 重叠,则可以改为为它们每个添加一个 activity_id,但这不再理想。【参考方案2】:

不幸的是,我们最终得到了最丑陋的答案,即为每种不同类型的条目(job_notes、project_notes 和 subproject_notes)都有一个注释表。我们这样做的原因如下:

具有包含联结“类型”列的单个联结表性能较差,因为没有一个外键是“真实的”并且必须手动搜索。注释字段包含每个条目的大量文本这一事实使情况更加复杂。

每个条目的联结表增加了一个额外的表,而不是简单地为每种表类型设置单独的注释表,虽然它看起来稍微漂亮一些,但它并没有带来实质性的性能提升。

我对这个答案不满意,因为为正在描述的每个作业/项目/子项目表有效地复制同一个 Notes 表似乎太浪费了。但是,我们还没有找到一个能够长期保持性能的答案。如果有人对如何执行此操作有更好的建议,我会保持打开状态!

【讨论】:

以上是关于几个多对多关系到一张表的主要内容,如果未能解决你的问题,请参考以下文章

Laravel一张表连接到另外两个由多对多的关系

SQL Server Analysis Services 中的多对多关系;第二个多对多关系不起作用

与 Laravel 的友谊系统:多对多关系

Laravel5.1 模型 --多对多关系

Python Django 多对多三种创建方式 form组件 cookie和session

Kohana 3 ORM:如何使用 2 个多对多关系执行查询