四个数据库表之间的多重关系的反规范化和减少冗余
Denormalization and reducing redundancy in multiple relationships among four database tables
我正在帮助一位社会科学家分析他的研究结果。他记录了数百次采访和其他会议,并收集了相关文件。他已将有关这项工作的数据输入到 MS Access 中的四个 table 中:
+---------+-----------+-----------------------------------------------------+
| Table | Key | Example contents |
+---------+-----------+-----------------------------------------------------+
| cases | ID_Case | Description, case data |
| persons | ID_Person | Name, contact data |
| events | ID_Event | Date, time, location of interview, meeting, etc. |
| files | ID_File | Path, filename, date of recordings, documents, etc. |
+---------+-----------+-----------------------------------------------------+
我们可以称它们为 "base" tables.
为了表示这些 table 之间的关系,他首先尝试了一组六个 table 链接到它们键上的原始四个:
+--------------+---------------------+
| Table | Key |
+--------------+---------------------+
| CasePersons | ID_Case, ID_Person |
| CaseEvents | ID_Case, ID_Event |
| CaseFiles | ID_Case, ID_File |
| EventPersons | ID_Event, ID_Person |
| EventFiles | ID_Event, ID_File |
| FilePersons | ID_File, ID_Person |
+--------------+---------------------+
我们可以称这些为 "binary relationship" tables.
示例场景(虚构)
这里是一个假想的场景来演示他的数据结构的例子。该场景涉及三个案例、七个人、三个事件和五个文件。
假设他对人们的爱情生活进行了两次采访。一个是对四个人的采访:乔治、莎莉、亨利和埃利奥特。第二次采访是对两个人的采访,John 和 Liz。第一次采访是视频录制的,第二次是音频录制的。第一次采访的一部分是单独录制的,只有 Sally 和 Henry。尽管 Liz 参加了第二次采访,但她没有说话,因此不在录音中。在第一次采访中,乔治分享了一封给莎莉的情书,扫描成 pdf 文件。最后,第三个活动是phone和同事开会,谈的是技术,没有讨论具体案例。
来自这个假想场景的数据显示在下面的 table 中。在每个 table 的名称旁边,我给出了数据库中实际 table 中的记录数。
四基Tables
Table [案例] (386 条记录)
+---------+---------------------------------+
| ID_Case | Description |
+---------+---------------------------------+
| 1 | A husband and wife are in love. |
| 2 | A man and woman are in love. |
| 3 | A man has never been in love. |
+---------+---------------------------------+
Table [人](1,472 条记录)
+-----------+-----------+----------+
| ID_Person | NameFirst | NameLast |
+-----------+-----------+----------+
| 1 | George | Brown |
| 2 | Sally | White |
| 3 | Henry | Green |
| 4 | John | Baker |
| 5 | Liz | Jones |
| 6 | Elliot | Brooks |
| 7 | Catherine | Drake |
+-----------+-----------+----------+
Table [事件](526 条记录)
+----------+------------+---------------+
| ID_Event | Date | Location |
+----------+------------+---------------+
| 1 | 2016 06 01 | 123 Main St. |
| 2 | 2016 07 02 | 456 Block Rd. |
| 3 | 2016 08 03 | Phone |
+----------+------------+---------------+
Table [文件](1,748 条记录)
+---------+---------------------------+------+
| ID_File | Filename | Type |
+---------+---------------------------+------+
| 1 | Brown, Brooks interview | avi |
| 2 | White, Green subinterview | avi |
| 3 | Brown letter | pdf |
| 4 | Baker interview | wav |
| 5 | Drake meeting | wav |
+---------+---------------------------+------+
六个二元关系Tables
在二元关系列表table中,我用相关文本替换了人物、事件和文件的键,以便于阅读。 MS Access 通过根据查询显示 table 字段来允许相同的行为。同样,某些 table 中显示的角色是数字外键的文本显示,用于分隔 table 允许的角色。
Table [CasePersons](720 条记录)
+---------+-----------+---------------+
| ID_Case | ID_Person | Role |
+---------+-----------+---------------+
| 1 | George | Husband |
| 1 | Sally | Wife |
| 1 | Henry | Wife's friend |
| 2 | John | Boyfriend |
| 2 | Liz | Girlfriend |
| 3 | Elliot | Individual |
+---------+-----------+---------------+
Table [CaseEvents](299 条记录)
+---------+------------+
| ID_Case | ID_Event |
+---------+------------+
| 1 | 2016 06 01 |
| 2 | 2016 07 02 |
| 3 | 2016 06 01 |
+---------+------------+
Table [CaseFiles](301 条记录)
+---------+---------------------------+
| ID_Case | ID_File |
+---------+---------------------------+
| 1 | Brown, Brooks interview |
| 1 | White, Green subinterview |
| 1 | Brown letter |
| 2 | Baker interview |
| 3 | Brown, Brooks interview |
+---------+---------------------------+
Table [EventPersons](700 条记录)
+------------+-----------+-------------+
| ID_Event | ID_Person | Role |
+------------+-----------+-------------+
| 2016 06 01 | George | Interviewed |
| 2016 06 01 | Sally | Interviewed |
| 2016 06 01 | Henry | Interviewed |
| 2016 06 01 | Elliot | Interviewed |
| 2016 07 02 | John | Interviewed |
| 2016 07 02 | Liz | Present |
| 2016 08 03 | Catherine | Present |
+------------+-----------+-------------+
Table [事件文件](1,490 条记录)
+------------+---------------------------+-----------+
| ID_Event | ID_File | Role |
+------------+---------------------------+-----------+
| 2016 06 01 | Brown, Brooks interview | Recording |
| 2016 06 01 | White, Green subinterview | Recording |
| 2016 06 01 | Brown letter | Received |
| 2016 07 02 | Baker interview | Recording |
| 2016 08 03 | Drake meeting | Recording |
+------------+---------------------------+-----------+
Table [FilePersons](2,392 条记录)
+---------------------------+-----------+-------------+
| ID_File | ID_Person | Role |
+---------------------------+-----------+-------------+
| Brown, Brooks interview | George | Interviewed |
| Brown, Brooks interview | Sally | Interviewed |
| Brown, Brooks interview | Henry | Interviewed |
| Brown, Brooks interview | Elliot | Interviewed |
| Brown letter | George | Writer |
| Brown letter | Sally | Subject |
| White, Green subinterview | Sally | Interviewed |
| White, Green subinterview | Henry | Interviewed |
| Baker interview | John | Interviewed |
| Drake meeting | Catherine | Present |
+---------------------------+-----------+-------------+
问题是在所有这些 table 中输入的数据有很多冗余。数百次采访,很容易出错,要么输入错误的某些数据,要么忘记输入所有六个二元关系 table 中的所有数据。一旦输入数据,就很难检查它们是否有错误。此外,冗余使得在数据中找到有意义的模式变得更加困难。
单身Four-Way关系Table
我一直在努力帮助他找出如何以更易于管理的方式表示这些数据。我一直在探索的一个想法是将六个二元关系 table 组合成一个具有四个关键字段的 table:ID_Case、ID_Person、ID_Event,以及 ID_File。那么上面的数据就变成了:
Table [CasePersonEventFiles] (??? 记录)
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
| ID_Case | ID_Person | ID_Event | ID_File | CP_Role | EP_Role | EF_Role | FP_Role |
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
| 1 | George | 2016 06 01 | Brown, Brooks interview | Husband | Interviewed | Recording | Interviewed |
| 1 | Sally | 2016 06 01 | Brown, Brooks interview | Wife | Interviewed | * Recording | Interviewed |
| 1 | Henry | 2016 06 01 | Brown, Brooks interview | Wife's friend | Interviewed | * Recording | Interviewed |
| 1 | Sally | 2016 06 01 | White, Green subinterview | * Wife | * Interviewed | Recording | Interviewed |
| 1 | Henry | 2016 06 01 | White, Green subinterview | * Wife's friend | * Interviewed | * Recording | Interviewed |
| 1 | George | 2016 06 01 | Brown letter | * Husband | * Interviewed | Received | Writer |
| 1 | Sally | 2016 06 01 | Brown letter | * Wife | * Interviewed | * Received | Subject |
| 2 | John | 2016 07 02 | Baker interview | Boyfriend | Interviewed | Recording | Interviewed |
| 2 | Liz | 2016 07 02 | 0 | Girlfriend | Present | | |
| 3 | Elliot | 2016 06 01 | Brown, Brooks interview | Individual | Interviewed | * Recording | Interviewed |
| 0 | Catherine | 2016 08 03 | Drake meeting | | Present | Recording | Present |
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
显然,这更简洁、更紧凑。数据行数已从 6 table 中的 36 条减少到 1 条中的 11 行。数据元素(non-null 个单元格)数量的减少并不显着,从 100 个减少到 85 个。相关数据非常接近,可以更轻松地避免错误或查看任何存在的错误。
在此 table 中,使用零代替空值,以便允许前四个字段形成主键,确保这四个字段之间的唯一性。在字段名称中,例如"CP_Role",表示"Case-person role",即此人在案例中的角色。
冗余减少了,但没有消除。与其他冗余的十三个数据元素在此示例中用星号标记。这种冗余是对 data-entry 错误的有害邀请。但是,在 table.
中自动检查此类错误相当简单
现阶段实现此 four-way 关系 table 的最大问题是将数据从六个二进制 table 折叠到其中。创建一个包含所有必需字段的 table 很容易,然后将六个 table 的所有行附加到其中,对于缺少的键,值为零。这使得 5,902 条记录的组合 table。如果上面示例场景中的数字可以外推到真实数据,那么记录的数量可以减少到大约 1,800 条,这意味着可以删除 4,000 多条记录!我目前正在研究组合中的模式d table,寻求自动合并和删除多余行组的方法。很slow-going。
比制作这个新 table 所花费的时间更糟糕的是,我不完全相信结果将是数据的最佳表示。
问题
我是否遗漏了这种方法中的重要内容?有没有更智能的方法来管理这些 collection 数据?数据库理论是否提供了一种更好的方式来表示这些关系?
您可以在任何数据库书籍中找到如何构建数据库。例如我想出了:
接下来我们需要一些数据输入表单。数据输入表格旨在获取案例数据并将其分类到适当的数据库表中。所以数据输入者不需要知道数据库的结构,只需要输入实际的数据。很难找到有关为一对多和多对多表格制作数据输入表格的信息。这是一个 link:
create form to add records in multiple tables
这是我为此数据制作的数据输入表单和最终子表单:
1 对 m 关系的第 1 侧是表单,第 m 侧是子表单。在这里,我将使用向导创建的 file/persons 表单拖到同样使用向导创建的文件表单上。为了能够表示第二个 1 到 m 关系,我们将表单上保存外键的文本框替换为组合框。这里 ID_Person 已被组合框替换,因此数据输入者不必知道任何有关 ID_person 的信息,而只需选择人员姓名即可。
结果是数据输入者不需要了解数据库中的关键关系,只需输入案例数据即可。
我正在帮助一位社会科学家分析他的研究结果。他记录了数百次采访和其他会议,并收集了相关文件。他已将有关这项工作的数据输入到 MS Access 中的四个 table 中:
+---------+-----------+-----------------------------------------------------+
| Table | Key | Example contents |
+---------+-----------+-----------------------------------------------------+
| cases | ID_Case | Description, case data |
| persons | ID_Person | Name, contact data |
| events | ID_Event | Date, time, location of interview, meeting, etc. |
| files | ID_File | Path, filename, date of recordings, documents, etc. |
+---------+-----------+-----------------------------------------------------+
我们可以称它们为 "base" tables.
为了表示这些 table 之间的关系,他首先尝试了一组六个 table 链接到它们键上的原始四个:
+--------------+---------------------+
| Table | Key |
+--------------+---------------------+
| CasePersons | ID_Case, ID_Person |
| CaseEvents | ID_Case, ID_Event |
| CaseFiles | ID_Case, ID_File |
| EventPersons | ID_Event, ID_Person |
| EventFiles | ID_Event, ID_File |
| FilePersons | ID_File, ID_Person |
+--------------+---------------------+
我们可以称这些为 "binary relationship" tables.
示例场景(虚构)
这里是一个假想的场景来演示他的数据结构的例子。该场景涉及三个案例、七个人、三个事件和五个文件。
假设他对人们的爱情生活进行了两次采访。一个是对四个人的采访:乔治、莎莉、亨利和埃利奥特。第二次采访是对两个人的采访,John 和 Liz。第一次采访是视频录制的,第二次是音频录制的。第一次采访的一部分是单独录制的,只有 Sally 和 Henry。尽管 Liz 参加了第二次采访,但她没有说话,因此不在录音中。在第一次采访中,乔治分享了一封给莎莉的情书,扫描成 pdf 文件。最后,第三个活动是phone和同事开会,谈的是技术,没有讨论具体案例。
来自这个假想场景的数据显示在下面的 table 中。在每个 table 的名称旁边,我给出了数据库中实际 table 中的记录数。
四基Tables
Table [案例] (386 条记录)
+---------+---------------------------------+
| ID_Case | Description |
+---------+---------------------------------+
| 1 | A husband and wife are in love. |
| 2 | A man and woman are in love. |
| 3 | A man has never been in love. |
+---------+---------------------------------+
Table [人](1,472 条记录)
+-----------+-----------+----------+
| ID_Person | NameFirst | NameLast |
+-----------+-----------+----------+
| 1 | George | Brown |
| 2 | Sally | White |
| 3 | Henry | Green |
| 4 | John | Baker |
| 5 | Liz | Jones |
| 6 | Elliot | Brooks |
| 7 | Catherine | Drake |
+-----------+-----------+----------+
Table [事件](526 条记录)
+----------+------------+---------------+
| ID_Event | Date | Location |
+----------+------------+---------------+
| 1 | 2016 06 01 | 123 Main St. |
| 2 | 2016 07 02 | 456 Block Rd. |
| 3 | 2016 08 03 | Phone |
+----------+------------+---------------+
Table [文件](1,748 条记录)
+---------+---------------------------+------+
| ID_File | Filename | Type |
+---------+---------------------------+------+
| 1 | Brown, Brooks interview | avi |
| 2 | White, Green subinterview | avi |
| 3 | Brown letter | pdf |
| 4 | Baker interview | wav |
| 5 | Drake meeting | wav |
+---------+---------------------------+------+
六个二元关系Tables
在二元关系列表table中,我用相关文本替换了人物、事件和文件的键,以便于阅读。 MS Access 通过根据查询显示 table 字段来允许相同的行为。同样,某些 table 中显示的角色是数字外键的文本显示,用于分隔 table 允许的角色。
Table [CasePersons](720 条记录)
+---------+-----------+---------------+
| ID_Case | ID_Person | Role |
+---------+-----------+---------------+
| 1 | George | Husband |
| 1 | Sally | Wife |
| 1 | Henry | Wife's friend |
| 2 | John | Boyfriend |
| 2 | Liz | Girlfriend |
| 3 | Elliot | Individual |
+---------+-----------+---------------+
Table [CaseEvents](299 条记录)
+---------+------------+
| ID_Case | ID_Event |
+---------+------------+
| 1 | 2016 06 01 |
| 2 | 2016 07 02 |
| 3 | 2016 06 01 |
+---------+------------+
Table [CaseFiles](301 条记录)
+---------+---------------------------+
| ID_Case | ID_File |
+---------+---------------------------+
| 1 | Brown, Brooks interview |
| 1 | White, Green subinterview |
| 1 | Brown letter |
| 2 | Baker interview |
| 3 | Brown, Brooks interview |
+---------+---------------------------+
Table [EventPersons](700 条记录)
+------------+-----------+-------------+
| ID_Event | ID_Person | Role |
+------------+-----------+-------------+
| 2016 06 01 | George | Interviewed |
| 2016 06 01 | Sally | Interviewed |
| 2016 06 01 | Henry | Interviewed |
| 2016 06 01 | Elliot | Interviewed |
| 2016 07 02 | John | Interviewed |
| 2016 07 02 | Liz | Present |
| 2016 08 03 | Catherine | Present |
+------------+-----------+-------------+
Table [事件文件](1,490 条记录)
+------------+---------------------------+-----------+
| ID_Event | ID_File | Role |
+------------+---------------------------+-----------+
| 2016 06 01 | Brown, Brooks interview | Recording |
| 2016 06 01 | White, Green subinterview | Recording |
| 2016 06 01 | Brown letter | Received |
| 2016 07 02 | Baker interview | Recording |
| 2016 08 03 | Drake meeting | Recording |
+------------+---------------------------+-----------+
Table [FilePersons](2,392 条记录)
+---------------------------+-----------+-------------+
| ID_File | ID_Person | Role |
+---------------------------+-----------+-------------+
| Brown, Brooks interview | George | Interviewed |
| Brown, Brooks interview | Sally | Interviewed |
| Brown, Brooks interview | Henry | Interviewed |
| Brown, Brooks interview | Elliot | Interviewed |
| Brown letter | George | Writer |
| Brown letter | Sally | Subject |
| White, Green subinterview | Sally | Interviewed |
| White, Green subinterview | Henry | Interviewed |
| Baker interview | John | Interviewed |
| Drake meeting | Catherine | Present |
+---------------------------+-----------+-------------+
问题是在所有这些 table 中输入的数据有很多冗余。数百次采访,很容易出错,要么输入错误的某些数据,要么忘记输入所有六个二元关系 table 中的所有数据。一旦输入数据,就很难检查它们是否有错误。此外,冗余使得在数据中找到有意义的模式变得更加困难。
单身Four-Way关系Table
我一直在努力帮助他找出如何以更易于管理的方式表示这些数据。我一直在探索的一个想法是将六个二元关系 table 组合成一个具有四个关键字段的 table:ID_Case、ID_Person、ID_Event,以及 ID_File。那么上面的数据就变成了:
Table [CasePersonEventFiles] (??? 记录)
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
| ID_Case | ID_Person | ID_Event | ID_File | CP_Role | EP_Role | EF_Role | FP_Role |
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
| 1 | George | 2016 06 01 | Brown, Brooks interview | Husband | Interviewed | Recording | Interviewed |
| 1 | Sally | 2016 06 01 | Brown, Brooks interview | Wife | Interviewed | * Recording | Interviewed |
| 1 | Henry | 2016 06 01 | Brown, Brooks interview | Wife's friend | Interviewed | * Recording | Interviewed |
| 1 | Sally | 2016 06 01 | White, Green subinterview | * Wife | * Interviewed | Recording | Interviewed |
| 1 | Henry | 2016 06 01 | White, Green subinterview | * Wife's friend | * Interviewed | * Recording | Interviewed |
| 1 | George | 2016 06 01 | Brown letter | * Husband | * Interviewed | Received | Writer |
| 1 | Sally | 2016 06 01 | Brown letter | * Wife | * Interviewed | * Received | Subject |
| 2 | John | 2016 07 02 | Baker interview | Boyfriend | Interviewed | Recording | Interviewed |
| 2 | Liz | 2016 07 02 | 0 | Girlfriend | Present | | |
| 3 | Elliot | 2016 06 01 | Brown, Brooks interview | Individual | Interviewed | * Recording | Interviewed |
| 0 | Catherine | 2016 08 03 | Drake meeting | | Present | Recording | Present |
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
显然,这更简洁、更紧凑。数据行数已从 6 table 中的 36 条减少到 1 条中的 11 行。数据元素(non-null 个单元格)数量的减少并不显着,从 100 个减少到 85 个。相关数据非常接近,可以更轻松地避免错误或查看任何存在的错误。
在此 table 中,使用零代替空值,以便允许前四个字段形成主键,确保这四个字段之间的唯一性。在字段名称中,例如"CP_Role",表示"Case-person role",即此人在案例中的角色。
冗余减少了,但没有消除。与其他冗余的十三个数据元素在此示例中用星号标记。这种冗余是对 data-entry 错误的有害邀请。但是,在 table.
中自动检查此类错误相当简单现阶段实现此 four-way 关系 table 的最大问题是将数据从六个二进制 table 折叠到其中。创建一个包含所有必需字段的 table 很容易,然后将六个 table 的所有行附加到其中,对于缺少的键,值为零。这使得 5,902 条记录的组合 table。如果上面示例场景中的数字可以外推到真实数据,那么记录的数量可以减少到大约 1,800 条,这意味着可以删除 4,000 多条记录!我目前正在研究组合中的模式d table,寻求自动合并和删除多余行组的方法。很slow-going。
比制作这个新 table 所花费的时间更糟糕的是,我不完全相信结果将是数据的最佳表示。
问题
我是否遗漏了这种方法中的重要内容?有没有更智能的方法来管理这些 collection 数据?数据库理论是否提供了一种更好的方式来表示这些关系?
您可以在任何数据库书籍中找到如何构建数据库。例如我想出了:
接下来我们需要一些数据输入表单。数据输入表格旨在获取案例数据并将其分类到适当的数据库表中。所以数据输入者不需要知道数据库的结构,只需要输入实际的数据。很难找到有关为一对多和多对多表格制作数据输入表格的信息。这是一个 link:
create form to add records in multiple tables
这是我为此数据制作的数据输入表单和最终子表单:
1 对 m 关系的第 1 侧是表单,第 m 侧是子表单。在这里,我将使用向导创建的 file/persons 表单拖到同样使用向导创建的文件表单上。为了能够表示第二个 1 到 m 关系,我们将表单上保存外键的文本框替换为组合框。这里 ID_Person 已被组合框替换,因此数据输入者不必知道任何有关 ID_person 的信息,而只需选择人员姓名即可。 结果是数据输入者不需要了解数据库中的关键关系,只需输入案例数据即可。