【问题标题】:Database design - How to handle conditional data数据库设计 - 如何处理条件数据
【发布时间】:2019-02-27 07:23:48
【问题描述】:

这似乎是 this question 的重复,但我已经检查过它并没有回答我的情况。

我的情况

考虑这两个表:

patients                           |     vaccines                
                                   |
id | name     | birthdate          |     id | name
---------------------------        |     ---------------
1  | John Doe | 1994-03-12         |     1  | Tetanus
---------------------------        |     ---------------
2  | Jane Doe | 1996-80-02         |     2  | Hepatitis A

还有这个数据透视表

patient_vaccine

id | patient_id | vaccine_id | date_received | comment
----------------------------------------------------------------
1  | 1          | 1          | 2019-01-01    | Lorem ipsum dolor set
----------------------------------------------------------------
2  | 1          | 2          | 2019-01-12    | Lorem ipsum dolor set
----------------------------------------------------------------
3  | 2          | 1          | 2018-09-21    | Lorem ipsum dolor set

很明显,如果说特定患者接种了特定疫苗,则会在数据透视表中插入一条新记录,其中包含 patient_idvaccine_id 以及其他数据。

但我有一种情况,如果患者未满 18 岁,则不会有 vaccine_id,而是会出现 took_all_vaccines 布尔值。

我的问题

更好的是,将 18 岁以下的患者数据放在一个单独的表格中,如下所示:

id | patient_id | took_all_vaccines | date_received | comment
----------------------------------------------------------------
1  | 1          | 1                 | 2019-01-01    | Lorem ipsum dolor set
----------------------------------------------------------------
2  | 1          | 0                 | 2019-01-12    | Lorem ipsum dolor set
----------------------------------------------------------------
3  | 2          | 9                 | 2018-09-21    | Lorem ipsum dolor set

或者我应该将 took_all_vaccines 列放在数据透视表中,并使其可以为空,对于 18 岁以上的人来说它是空的,这也需要让 vaccine_id 列对于 18 岁以下的人可以为空.

所以我最终会得到这样的结果:

id | patient_id | vaccine_id | took_all_vaccines | date_received | comment
-----------------------------------------------------------------------------
1  | 1          | 1          | null              | 2019-01-01    | Lorem ipsum dolor set
-----------------------------------------------------------------------------
2  | 1          | 2          | null              | 2019-01-12    | Lorem ipsum dolor set
-----------------------------------------------------------------------------
3  | 2          | null       | 1                 | 2018-09-21    | Lorem ipsum dolor set

如果一个解决方案更好,为什么?为什么另一个不是?

【问题讨论】:

  • 只需在表格左侧添加一个名为 injection_ID 或类似名称的 ID。然后,当您选择时,您可以取消所有注射,并查看针对特定患者的疫苗。
  • @AbsoluteƵERØ 会将所有与 18 岁以下相关的列移动到另一个表,但我仍然需要 vaccine_id 列为空,我认为这不是一件好事,尤其是它是一个外键。
  • “服用所有疫苗”可能会过时。
  • @KebabProgrammer 为了表明 18 岁以下的患者是否接种了所有疫苗,在这种情况下不能有 vaccine_id
  • 我认为您最好使用第二种方法,因为您始终可以根据程序的条件更新vaccine_idtook_all_vaccines。如果设置了vaccine_id,则took_all_vaccines 为空,反之亦然。

标签: mysql database database-design database-schema


【解决方案1】:

您称为数据透视表的表在标准关系设计中通常称为多对多解析器表。这是因为,在高层次上,您的设计涉及患者和疫苗之间的多对多关系。

  • 患者可以接种多种疫苗
  • 许多患者都可以接种疫苗

现在回答您的具体问题:

这里没有完美的答案,因为这是正常关系之外存在的业务规则,但我会做两种不同的事情之一。

关于疫苗的第一件事是 AFAIK,多种疫苗通常在一次注射中结合使用。因此,这需要“注射”表或疫苗表支持父子层次结构的能力。

“服用所有疫苗”在我看来是一种不具体且事实上不准确的表述,但我又不知道您的申请。

鉴于此,我认为最简单和最好的答案是在疫苗中添加一行名为“所有疫苗(18 岁以下的患者)”。

那么您就不再需要关心 NULL 外键,这在多对多解析表中肯定是不希望的。

另一种选择是实现注射容器表(注射 1 -> 许多疫苗)并让患者注射替换患者疫苗。您还可以通过将注射和疫苗组合到一个层次表中来做类似的事情,其中​​疫苗可以有一个父“疫苗”行。

【讨论】:

  • 在多对多关系中,实际上没有表的标准术语。我听说它叫做桥表、交叉表等。
  • @BillKarwin 同意 Codd 对此一无所知,但根据我与其他 DBA、开发人员和架构师的经验,这是相当标准的说法。我提出这个问题的原因是,数据透视表完全是另外一回事,与 Excel 或数据仓库特别相关。
  • 所以,是的..经过更多研究,确实没有完美的答案,这往往是一个更何时拆分表的情况。
【解决方案2】:

我不会实施该标志或将“服用所有疫苗”作为条目添加到患者疫苗表中。

原因: 明天,您可能会决定添加一种新疫苗,而目前标记为已接种所有疫苗的所有患者的结果将被破坏。您将失去他们没有接种新添加疫苗的踪迹。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 2016-05-29
    • 2017-11-28
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2021-03-20
    相关资源
    最近更新 更多