【问题标题】:Correct normalization of database with optional columns使用可选列正确规范化数据库
【发布时间】:2010-11-18 02:44:57
【问题描述】:

我需要创建一个数据库表来存储一组假设患者的生理特征(例如收缩压、甘油三酯浓度等)的参数描述。

例如,假设用户为 SBP 指定三角分布,则必须存储最小值、最大值和众数(以及分布类型)。或者,用户可以指定一个正态分布,需要存储平均值和标准差。

我正在努力寻找正确的方法来规范化这些数据。目前,我有一个 Cohort 表和一个 Distribution 表,其中包含许多一对一的关系,如下所示(省略了一些字段):

队列 id(INT,NOT NULL,PRIMARY) 名称(文本,非空) cmets (文本) systolic_blood_pressure_dist(引用 Distributions.id 的外键) triglyceride_dist(引用 Distributions.id 的外键) ...其他生理参数 分布 id(INT,NOT NULL,PRIMARY) 分布类型(文本) 最小值(浮动) 最大(浮动) 平均值(浮点数) 模式(浮动) sd(浮点数) ...其他分布参数(α、β、形状、比例等)

(distribution_type 包含一个描述分布的字符串:“Triangular”、“Weibull”等)

我很确定这不是执行此操作的最佳方法,因为我在 Distributions 的每一行中都有大量 NULL 字段。

我的另一个想法是为每种分布类型设置单独的表(一个用于三角形,一个用于高斯,一个用于均匀等),并在中间有一个带有 id 列的表(用作外键在 Cohort 表 *_dist 列中)、一个分布类型列和一个 id 列,用于存储相应分布表中行的外键。

查询将使用存储在 Cohort 列中的 id 从中间表中查找分布类型和行 id,然后使用 id 在适当的表中查找参数。但是,使用一个字符串来选择合适的表,然后另一个id来选择合适的行,这与传统的JOIN相差甚远,也感觉不是一种很干净的方法。

那么,对于如何最好地实现这一点(在标准化和/或性能方面),是否有人有任何建议?

非常感谢, 丰富

【问题讨论】:

    标签: mysql database database-design normalization


    【解决方案1】:
    Cohort
        id (INT, NOT NULL, PRIMARY)
        name (TEXT, NOT NULL)
        comments (TEXT)
    
    Parameters
        id (INT, NOT NULL, PRIMARY)
        name (TEXT, NOT NULL) ("systolic blood pressure", "trygliceride", ...)
    
    CohortParameters
        id (INT, NOT NULL, PRIMARY)
        cohort_id (FOREIGN KEY referencing Cohort.id)
        parameter_id (FOREIGN KEY referencing Parameters.id)
        value (TEXT)
    
    DistributionTypes
        id (INT, NOT NULL, PRIMARY)
        name (TEXT, NOT NULL) ("Triangular", "Weibull", ...)
    
    Distributions
        id (INT, NOT NULL, PRIMARY)
        distribution_type_id (FOREIGN KEY referencing DistributionTypes.id)
        cohort_id (FOREIGN KEY referencing Cohort.id)
        parameter_id (FOREIGN KEY referencing Parameter.id)
        minimum (FLOAT)
        maximum (FLOAT)
        mean (FLOAT)
        mode (FLOAT)
        sd (FLOAT)
        ...other distribution parameters (alpha, beta, shape, scale, etc.)
    

    【讨论】:

    • 非常感谢您的及时回复!我对解决方案的几个方面有点不清楚,特别是 CohortParameters 表 - 它的目的是什么以及 value 列的用途是什么?此外,Distributions 表仍然会存在 NULL 值问题(尽管可以忽略不计的浪费空间,但我仍然没有说服自己这确实是一个问题......)。再次感谢您对此的投入,Rich。
    【解决方案2】:

    对我来说,为不同的分布类型设置单独的表格听起来不错。在您的应用程序逻辑中,无论如何(我认为)您都必须对每种分发类型进行特殊处理,因为它可能需要在 UI 中进行不同的渲染或不同的计算。

    【讨论】:

      【解决方案3】:

      您可能想要为每种分布类型创建一个表格。这样,您就有了一个定义明确的表格,其中包含特定于您的分配类型所需的每个值。这将节省您的空间,将允许您锁定哪些字段可以为空,哪些不可以,并且会提高性能。如果每个分布都有一组共同的参数,您可以按照超类型/子类型关系排列表,以进一步规范模式。

      【讨论】:

        【解决方案4】:

        查询时如何使用数据?

        如果您要查询多个群组,并且群组具有不同分布是合理的,那么您的结果将是一个“联合”,其中许多列确实为空。在这种情况下,您的结果在某种意义上是“不正常的”,但这并不意味着架构应该是。

        为不同的分布类型使用不同的表的好处是,每个表都会明确定义必须填充以描述该分布的列,您甚至可以将某些列设置为“非空”。

        我喜欢你提案的总体思路。

        【讨论】:

        • 非常感谢您的回复(也感谢上面的 Martin 和 Dave)。我不会经常查询多个队列,所以 UNION 不会参与。我很高兴您同意“不同的表用于不同的分布”的想法,但我在实施时遇到了问题。在我的中间表(将群组与分布相关联)中,我将 dist_ID 存储在一个列中,但我只能通过查询 dist_type 列知道它指的是哪个表。因此,我不能使用任何 InnoDB 的引用完整性功能,如级联删除。有什么想法吗?也许另一个问题是为了......
        【解决方案5】:

        您的设计似乎表明每项测量信息只能有一种类型的分布数据。在您的设计中,似乎不可能同时拥有“均匀分布”和“三角分布”数据,例如“收缩压”。

        这似乎表明,对于每个单独的“测量信息”,您在系统设计时就已经预先知道了可用的分布数据类型。

        这反过来似乎表明没有必要将这些不同类型的分布收集到一个集合中(从关系的角度来看,这样做是非常糟糕的),只是为了恢复任何必要的通过添加一个多余的“分布类型”列来区分。

        编辑

        “一旦数据库中有两个或多个具有不同分布生理参数的群组,分布类型列也变得必要。”

        这似乎是废话。不同的同类群组拥有不同的分布测量 ID,而不同的分布测量 ID 可以根据您自己的设计具有不同的分布类型。

        【讨论】:

        • 每条测量信息只能有一个分布在任何时候,但分布类型可以由用户通过网络界面更改(取决于临床试验例如,他们正在使用的数据)。一旦数据库中有两个或更多具有不同分布的生理参数的群组,分布类型列也变得必要。希望对您有所帮助。
        • “不同的群组拥有不同的分布测量 ID,不同的分布测量 ID 可以根据您自己的设计具有不同的分布类型。”为什么这会使分配类型列的要求“废话”?我仍然需要一些东西来将每个队列特征与其分布联系起来,如果每个分布类型都存储在不同的表中,那么我需要一些方法来识别它在哪个表中。虽然它确实不需要 在队列表本身中,我很确定 3NF 规定它应该在那里。
        猜你喜欢
        • 2014-07-29
        • 1970-01-01
        • 1970-01-01
        • 2018-01-27
        • 2017-08-04
        • 2012-10-08
        • 2012-06-21
        相关资源
        最近更新 更多