【发布时间】:2018-03-31 15:15:57
【问题描述】:
我正在帮助一位社会科学家分析他的研究结果。他记录了数百次采访和其他会议,并收集了相关文件。他已将这项工作的数据输入到 MS Access 的四个表中:
+---------+-----------+-----------------------------------------------------+
| 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. |
+---------+-----------+-----------------------------------------------------+
我们可以称这些为“基础”表。
为了表示这些表之间的关系,他首先尝试了一组六个表,它们在键上链接到原来的四个:
+--------------+---------------------+
| 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 |
+--------------+---------------------+
我们可以将这些称为“二元关系”表。
示例场景(虚构)
这是一个假想的场景来演示他的数据结构的一个例子。该场景涉及三个案例、七个人、三个事件和五个文件。
假设他对人们的爱情生活进行了两次采访。其中之一是对四个人的采访:乔治、莎莉、亨利和艾略特。第二次采访是两个人,约翰和丽兹。第一次采访以视频录制,第二次以音频录制。第一次采访的一部分是由莎莉和亨利进行并单独录制的。 Liz虽然在第二次采访中,但她没有说话,所以没有出现在录音中。在第一次采访中,乔治分享了一封给莎莉的情书副本,该信被扫描成 pdf 文件。最后,第三件事是和同事的电话会议,是关于技术的,没有讨论具体的案例。
来自这个想象场景的数据显示在下表中。在每个表的名称旁边,我给出了数据库中实际表中的记录数。
四个基表
表[案例](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. |
+---------+---------------------------------+
表 [人](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 |
+-----------+-----------+----------+
表 [事件](526 条记录)
+----------+------------+---------------+
| ID_Event | Date | Location |
+----------+------------+---------------+
| 1 | 2016 06 01 | 123 Main St. |
| 2 | 2016 07 02 | 456 Block Rd. |
| 3 | 2016 08 03 | Phone |
+----------+------------+---------------+
表[文件](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 |
+---------+---------------------------+------+
六个二元关系表
在二元关系表列表中,我将人员、事件和文件的键替换为相关文本,以使其更易于阅读。 MS Access 通过根据查询显示表字段来允许相同的行为。同样,某些表格中显示的角色是数字外键的文本显示,用于分隔允许角色的表格。
表 [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 |
+---------+-----------+---------------+
表 [CaseEvents](299 条记录)
+---------+------------+
| ID_Case | ID_Event |
+---------+------------+
| 1 | 2016 06 01 |
| 2 | 2016 07 02 |
| 3 | 2016 06 01 |
+---------+------------+
表 [CaseFiles](301 条记录)
+---------+---------------------------+
| ID_Case | ID_File |
+---------+---------------------------+
| 1 | Brown, Brooks interview |
| 1 | White, Green subinterview |
| 1 | Brown letter |
| 2 | Baker interview |
| 3 | Brown, Brooks interview |
+---------+---------------------------+
表 [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 |
+------------+-----------+-------------+
表 [EventFiles](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 |
+------------+---------------------------+-----------+
表 [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 |
+---------------------------+-----------+-------------+
问题在于所有这些表中输入的数据都存在大量冗余。数百次面试很容易出错,要么输入错误的某些数据,要么忘记输入所有六个二元关系表中的所有数据。一旦输入数据,就很难检查它们是否有错误。此外,冗余使得在数据中找到有意义的模式变得更加困难。
单四向关系表
我一直在努力帮助他弄清楚如何以更易于管理的方式表示这些数据。我一直在探索的一个想法是将六个二元关系表组合成一个具有四个关键字段的表:ID_Case、ID_Person、ID_Event 和 ID_File。那么上面的数据就变成了:
表 [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 |
+---------+-----------+------------+---------------------------+-----------------+---------------+-------------+-------------+
显然,这更清洁、更紧凑。数据行数已从六张表中的 36 行减少到一张表中的 11 行。数据元素(非空单元格)数量的减少幅度较小,从 100 个减少到 85 个。相关数据非常接近,因此更容易避免错误或查看任何存在的错误。
在此表中,使用零而不是空值,以允许前四个字段形成主键,从而确保这四个字段的唯一性。在字段名称中,例如“CP_Role”表示“Case-person role”,即该人在案例中的角色。
冗余减少了,但没有消除。在此示例中,与其他数据元素冗余的 13 个数据元素用星号标记。这种冗余是对数据输入错误的有害邀请。但是,自动检查此表中的此类错误相当简单。
在这个阶段实现这个四向关系表的最大问题是从六个二进制表中将数据折叠到其中。很容易创建一个包含所有必要字段的表,然后将六个表的所有行附加到其中,其中缺少键的值为零。这构成了一个包含 5,902 条记录的组合表。如果上面示例场景中的数字可以外推到真实数据,那么记录的数量可以减少到大约 1800 条,这意味着可以删除超过 4000 条记录!我目前正在研究组合表中的模式,寻找自动合并和删除多余行组的方法。这是非常缓慢的。
比制作这个新表所花费的时间更糟糕的是,我不完全相信结果将是数据的最佳表示。
问题
我是否在这种方法中遗漏了一些重要的东西?有没有更智能的方法来管理这些数据集合?数据库理论是否提供了一种更好的方式来表示这些关系?
【问题讨论】:
-
对于dba.stackexchange.com 来说可能是个好问题。也许吧。
-
我想知道这一点。在这两个地方都可以发布吗?或者我可以在那里发帖链接到这里的问题吗?当一个问题适用于多个 StackExchange 板时,正确的做法是什么?
-
是时候阅读有关信息建模和数据库设计的教科书了。 PS您在某种意义上减少了某些冗余,但您也在增加某些有问题的冗余,您解决了这些问题,尽管不是冗余。您正在“反规范化”。 PS 表格代表应用程序/业务关系(船舶)/关联。表之间的“关系”[原文如此——尽管普遍存在] 是约束,即事实,即关系的实例“具有也必须出现在其中的子行”,即 FK。 (每个都与一个二进制关系(ship)/关联相关联,可以根据其引用的表来表达。)
-
对于任何特定的分解或(重新)组合/非规范化都没有绝对的好处。 Normalizaiton 说有些组合是好的,不要说其他的,并说其他的有问题;您可能仍然想要一个有问题的,同时管理问题。您可能会受益于设置值、列表值或表值列或空值列。您必须识别 FDs(函数依赖)(说明一列的值是其行中其他值的函数)和 JDs(连接依赖)(说明一个表等于它的预测)。教科书。
-
Something I just wrote. 也许谷歌我的其他答案是谓词、数据库设计和规范化。 Beware. 一些good stuff.
标签: database ms-access database-design relationship database-normalization