可选的数据库实体
Posted
技术标签:
【中文标题】可选的数据库实体【英文标题】:Optional Database Entities 【发布时间】:2009-08-31 19:47:25 【问题描述】:原创(请参阅下面的更新问题)
我正在设计一个新的实验室数据库,用于对各种样本类型的各种测试进行测试。
以下列表是我目前的候选主要实体列表,以最好地模拟实验室工作。
对于每个实体,从该实体到下面的实体存在一对多的关系。换句话说,每个实体(除了 REQ)至少有 entity_id 和 parent_id 的列。
主要实体:REQ:
申请(表格)SAM:
样品(材料)TST:
测试(申请手续)SUB:
**
子测试(标准测试的一部分)TRI:
**
试用(单个实例:通常用于平均值、范围和标准差)MEA:
测量(测量的数字)**
不是全部测试有子测试,并不是所有的测试都有试验。
子测试是一组按单个名称组合在一起的测试,以便于参考。例如,特定产品的批次验收测试 (LAT) 定义为以下测试:粘度、%-氮、pH 和密度。
试验是为保证产品而多次执行的单个试验。例如,可能射出 50 发子弹,每发子弹都是一次试验。每颗子弹的准确度可能需要在一定范围内,而所有五十发子弹的平均准确度可能需要在更窄的范围内。
问题:当不需要子测试和/或试验时,我应该如何建模案例?
选项 1:如果不需要,请使用“空白”子测试(或试验)。
选项 2: 将子测试和试验视为测试(并以 test_id 作为父项),以便测量始终以测试作为父项。
选项 3: 用于测量(试验、子测试或测试)和试验(子测试或测试)的可选父项。
选项 x:任何其他值得考虑的选项。
仅供参考:如果需要回答这个问题,我将使用 Oracle。
更新问题 一般来说,我的模式是实体的层次结构,其中每个实体(顶部除外)必须有一个父级,并且(底部除外)必须至少有一个子级。处理在某些情况下不需要内部实体的情况的最佳方法是什么,或者使用特定选项的好处/缺点是什么?
选项 1(虚拟):使用“虚拟”条目表示实体在这种情况下不适用。
选项 2(汇总):将可选实体汇总到下一个更高的父实体。
选项 3(Pick-a-Parent): 可选实体 (B) 下方的实体 (C) 和必需实体 (A) 必须有一个父级,但父级可以是可选实体 ( B)或下一个更高的(A)。
选项 x:任何其他值得考虑的选项。
【问题讨论】:
【参考方案1】:解决您的简化问题:
鉴于您描述的层次结构,如果我发现层次结构中的某些级别是可选的,我会质疑层次结构是否真的很好地映射到我的域。我会考虑以不同的方式绘制关系,或者重新定义架构中的实体。
我认为在如此短的篇幅内不可能对一般性问题提供更详细的答案,因为找出一个域的最佳表示是 a) 很难,并且 b) 对特定域非常具体。
【讨论】:
【参考方案2】:使用外部连接。 (右外连接和左外连接)。
它们是专门为此而制作的。
【讨论】:
【参考方案3】:这是我的第一篇文章。根据 cmets,我将添加第二个帖子。
这是我对建筑第一关的看法。这些东西通常需要与主题专家进行大量的反复讨论才能正确完成。
“测试”是指以下之一: - 采取行动,衡量结果 - 采取多项行动(子测试),衡量每个行动的结果 - 不做任何测试(但你仍然可以进行测量——?)
我会将其配置为“父”测试表和子“子测试”表,其中测试可以有 0 个或多个相关的子测试,并且每个子测试必须与一个且只有一个测试相关。 (如果一个测试只有一个 SubTest,请将其输入到自己的表中,不要尝试在 Test 表中跟踪 SubTest。)
只有存在 SubTests 时,Trials 才能存在。因此,Trials 是 SubTest 表的子表; SubTest 可以有零个或多个 Trials,Trials 必须与一个且仅一个 SubTest 相关。
只有在有试验的情况下才存在措施。因此,重复上述步骤,将Measures 作为Trials 的子项。
可以有没有试验(或测试)的子测试吗?如果是这样,请不要参加任何试炼。
可以有没有试验的措施吗?如果不是,您不需要任何试验(或子测试)。如果是 (?),请根据需要再次输入一些正确标记的虚拟/占位符子测试或试验。
同样,这是初步的,需要更多地采访那些有驾驶要求的人。
【讨论】:
所有实体(测量除外)必须至少有一个子实体。带有子测试的测试只是测试组的别名。一个(主)测试可能有零个或多个子测试和零个或多个试验。每个测量和试验(如果适用)都必须有一个父对象。 好吧,所有实体(请求除外)也必须有一个父实体。 我的名字分散了我的想法。总是有一个“主要”测试吗?它与 SubTests 有何不同?听起来“子测试”就是您所说的那些情况,因为测试有多个“主要”测试。如果所有测试都是平等的,那么将它们全部放在“SubTests”中;如果某些测试比其他测试更平等,我仍然会将它们粘贴在“SubTests”中并以某种方式将它们标记为更重要(IsMainTest = TRUE)。然后 Trials 只需要与 SubTests 相关,并且关系完整性更容易维护。 (续) 这里的命名法可能是个问题,有很多东西叫做“测试”。几年前,我在一家进行在线测试的公司工作,我们让测试人员在测试中心进行测试,测试中心监视器和测试结果,一切都是“测试”某事或其他连贯的对话设计几乎是不可能的。用考试、考生、监考人员、中心和开始有意义的事情来代替它们。 /结束闪回 我将使用选择比萨饼配料作为选择样本“测试”的类比。客户可以订购带有单独浇头的披萨(没有子测试的主测试)或选择特色披萨(主测试),这是一组常见浇头(子测试)的别名。【参考方案4】:正如其他人所说,如果不进一步了解您的域,我们很难给出明确的答案。您尝试将大量业务规则提炼成几段,但丢失了一些重要信息。具体来说,在不知道它们的属性的情况下,不可能确定两个实体是否真正不同。说了这么多,我们开始吧。
TEST
是单个过程。尽管包含“测试”一词,但 LAT 本身并不是TEST
,而是一组预定义的此类过程。我会将此场景建模为带有可选父实体的实体TEST
,我更愿意将其称为TEST_GROUP
(就是这样),但最好使用域名SUB_TEST
。
TRIAL
似乎与TEST
不同,因此将其建模为一个单独的实体。因此,当涉及到MEASUREMENT
时,您可以选择:您可以拥有一个具有两个可选外键的实体,或者您可以拥有TEST_MEASUREMENT
和TRIAL_MEASUREMENT
。选择哪条路取决于特征和使用情况。
以下是对实体关系的初步介绍。当用户说“哦,不,这根本不是我的意思”时,这将是项目中的重点。
create table sample (
sample_id number not null
, constraint samp_pk primary key (sample_id)
)
/
create table sub_test (
sub_test_id number not null
, sample_id number not null
, constraint subt_pk primary key (sub_test_id)
, constraint subt_samp_fk foreign key (sample_id)
references sample (sample_id)
)
/
create table test (
test_id number not null
, sample_id number not null
, sub_test_id number
, constraint tst_pk primary key (test_id)
, constraint tst_samp_fk foreign key (sample_id)
references sample (sample_id)
, constraint tst_subt_fk foreign key (sub_test_id)
references sub_test (sub_test_id)
)
/
create table trial (
trial_id number not null
, test_id number not null
, constraint trl_pk primary key (trial_id)
, constraint trl_tst_fk foreign key (test_id)
references test (test_id)
)
/
create table measurement (
measurement_id number not null
, trial_id number
, test_id number
, constraint meas_pk primary key (measurement_id)
, constraint meas_tst_fk foreign key (test_id)
references test (test_id)
, constraint meas_trl_fk foreign key (trial_id)
references trial (trial_id)
, constraint measurement_ck check (
(test_id is not null and trial_id is null)
or (test_id is null and trial_id is not null)
)
/
编辑
解决您更一般的问题。
选项 1(虚拟)
从不使用虚拟记录。这就像使用魔法值而不是空值。解决方案比它解决的问题更糟糕。
选项 2(汇总)
当父母和孩子具有相同的属性时,这可以工作。但是,如果它们有不同的列,或者它们是不同的依赖项,这不是一个可行的解决方案。即使它们具有相同的数据结构但不同的业务用途,这仍然可能是一个问题。
选项 3(选择父母)
这将是我的首选解决方案。障碍是需要一个检查约束来确保一个(并且只有一个)符合条件的外键已经被填充。您还需要防止让太多的父母/祖父母/曾祖父母参与其中。
【讨论】:
【参考方案5】:我不完全确定我理解你的问题的细节,但听起来你应该有以下几点:
表格测试 test_id,请求,样本,测试
表子测试 subtest_id, test_id(Test的外键)
桌试 trial_id、trial_name、measurement、subtest_id
所以,Test 是子测试的集合(可能只有一个子测试),而子测试是 Trials 的集合(可能只有一个 Trial)
【讨论】:
每个实体可以包含多个子实体。因此,每个实体(request除外)都至少有self_id、parent_id(当然把self和parent替换成对应的名字)。【参考方案6】:我不完全确定我了解您的域,但您能做这样的事情吗?
Tests
有一个parent_test_id
列,可以是NULL
(设置后,这是一个子测试)。
Trials
有一个 test_id
列。 (所有测试都至少有一次试验,因为你做了一件事并且至少进行了一次测量,对吧?)
Measurements
有一个 trial_id
列。
这似乎违反了你的前提,因为它规定所有测试至少有一次试验,所以我可能误解了要求。你怎么能在没有试验的情况下进行测试?
无论如何,如有必要,您可以将trial_id
和test_id
放在Measurements
上,可能有一个约束条件,即一个或另一个必须为NULL(另一个必须设置)。
【讨论】:
试验实体主要用于存在多个试验时。对单个值进行统计没有多大意义。 嗯。那么,您能否将通常存储在试验中的信息向下滚动到测量或向上滚动到测试,这取决于它们是应用于单个运行还是所有运行的集合?如果试验适用于单次运行,那么存储统计信息的位置似乎很奇怪(正如您所指出的那样)。如果一个测试只有一个测量,那么统计字段可能只是 NULL。 请在主帖中查看我的简化问题。【参考方案7】:根据我第一篇文章的反馈,我将对此进行第二次尝试。要理解的关键是设计和架构可以是高度迭代的,我怀疑你会在没有很多来回的情况下获得理想的模型——这在 Stack Overflow 上并不能很好地发挥作用。很有可能你会接受发布的想法(APC 有一些好的想法),与你的同事一起讨论,然后想出一些行得通的东西。
我这些天在设计数据库时的目标是尝试生成一个完全标准化的模型。一旦你得到了它,如果它看起来不合理或不实用,你可以为了效率、权宜之计或其他原因进行非规范化 - 但关键是你在找到理想模型之后进行非规范化 .如果你在完全规范化之前停止规范化,你就没有去规范化,你只是得到了一个草率的模型。
这是我迄今为止看到的实体:
您标记为***测试的内容,为了清楚起见,我将这里称为考试。您定义了一项检查及其所有内容(如下),然后人们联系您的实验室以针对他们的问题进行这些检查。
对于为客户执行的任何特定考试,您都会运行大量测试。任何给定的测试都可以被(要求?)任意数量的考试使用。
通常,您会获得一组针对多个考试一起完成的测试。如果有适用于特定测试集的属性,您可能希望将每个集标识为其自己的实体。调用这些 TestGroups。但是,如果这些仅用于将一组特定的测试与一个或多个考试相关联,那么将它们定义为自己的实体可能不会给您带来任何特别的好处。 (这些是您的子测试。)
因此,考试“具有”或“包含”一个或多个测试。或者,考试与一个或多个测试组相关。但是,尝试将考试与零个或多个 TestGroups 零个或多个单独的测试相关联会产生过于复杂的模型(更不用说物理实现了),我真的很想避免这种情况。也许一个 TestGroup 可以包含一个 Test,所以 Exams 只引用 TestGroups?也许考试只能与一个测试组相关——在这种情况下,这将是“多对多”表,将考试与测试相关联。这取决于与主题专家对需求的进一步讨论。
所以你有考试 - 考试定义,真的 - 以某种方式与多个测试相关。接下来,您有一个考试的“付费实例”(客户 X 进来并付钱给您测试他的小部件)。称之为CustomerExam;它包含所有联系信息和计费信息,标识要运行的考试,因此与要为客户执行的测试相关。 (那里可能也有一个客户实体......?)
试用是针对作为 CustomerExam 一部分的测试进行的。它们与考试或测试无关,它们是正在执行的试验的一个实例。 (似乎可以安全地假设试验的“含义/定义”实际上是测试的一部分——例如,如果测试 = 枪是准确的,那么试验所需的工作 = 开火 50 次,并且措施)。因此,为给定 CustomerExam 的测试执行试验。它们是执行一次,还是不止一次? (是试射 50 次,还是每次射击都算作一次试射?如果他们进行两轮 50 次射击呢?)无论如何,Trial 事件的属性都存储在这里——当它发生时,谁做了它,特别说明/情况,等等。
措施由(或为?)试验产生。每个度量的含义/定义实际上是 Trial 定义的一部分(这是 Test 定义的一部分);试验事件为定义/预期措施产生特定值。假设试验将生成零个 (?) 或多个度量,因此度量是它们自己的实体。
回想起来,似乎存在某种形式的隐含双重结构:一组表来定义可用的考试、测试、试验和测量(可以检查什么,如何测试,我们应该测量什么) 和一组配套的表来跟踪每个实例的特定实例(谁想要它,谁做了工作,他们什么时候做的,结果是什么)
我必须对这个问题有过分的了解。这里的关键是,与所有设计会议一样,在提出想法和提出问题时,它们是否产生了您自己的想法、问题或答案?
【讨论】:
以上是关于可选的数据库实体的主要内容,如果未能解决你的问题,请参考以下文章
Swift、Core Data、可选的 Integer16 和 keyPath
如何使用 BooleanBuilder (QueryDSL) 为可选的 OnetoOne JPA/Hibernate 关系建模谓词?