您将如何在通用方案上为数据变量方差建模?SQL

您将如何在通用方案上为数据变量方差建模?SQL,sql,mysql,database,database-design,normalization,Sql,Mysql,Database,Database Design,Normalization,我最近在想一些事情,我想知道什么是正确的方法来做下面的场景(我相信DB的家伙做这样的事情是很常见的)。 假设您有一个products表,类似于(MySQL): 这里没有什么不寻常的事。现在让我们假设在不同的表中有一个类别的层次结构,并且有一个单独的表,它绑定了与products表的多对多关系-因此每个产品都属于某种类别(我将省略这些,因为这不是这里的问题)。 现在有一个有趣的部分-如果每个类别都要求为产品项增加一组变量,该怎么办。例如,计算机显示器类别中的产品必须具有LCD/CRT枚举字段、

我最近在想一些事情,我想知道什么是正确的方法来做下面的场景(我相信DB的家伙做这样的事情是很常见的)。

假设您有一个products表,类似于(MySQL):

这里没有什么不寻常的事。现在让我们假设在不同的表中有一个类别的层次结构,并且有一个单独的表,它绑定了与products表的多对多关系-因此每个产品都属于某种类别(我将省略这些,因为这不是这里的问题)。

现在有一个有趣的部分-如果每个类别都要求为产品项增加一组变量,该怎么办。例如,计算机显示器类别中的产品必须具有LCD/CRT枚举字段、屏幕大小枚举等,以及其他类别,比如说冰淇淋具有一些其他变量,如风味varchar、货架存储时间int等。

这里的问题在于,所有产品都有一个共同的变量集(id、名称、描述等),但还有其他变量在不同类别之间不一致——但所有产品都应该共享一个共同的变量集,因为最终它们都属于产品组,因此,我们可以查询例如,按公司id从产品订单中选择*(简单的示例,可能不具有代表性,但您可以得到图片)。

现在,我看到了几个潜在的解决方案:
-为每个产品类别生成单独的表,并使用适当的附加变量存储产品-愚蠢且不便于查询

-产品表与常用变量保持一致,对于每个类别,创建一个单独的表,其中包含附加变量,并使用联接绑定两个表-规范化,但查询性能和清晰度问题-如何从类别中筛选产品(第一个表-产品)和额外变量的附加过滤器(17英寸LCD监视器ie.)-这需要SQL连接技巧

-products表保持不变,并添加另一个变量类型文本,该文本包含例如JSON数据,该数据包含其他变量—紧凑且整洁,但不能使用SQL过滤变量

我知道我在这里遗漏了一些非常明显和简单的东西——我对规范化技术有点生疏:)


编辑:在问这个问题之前,我一直在stackoverflow周围搜索,但没有成功。然而,在我发布了这个问题之后,我点击了我的一个标记“规范化”,并发现了几个类似的问题,导致查找“泛化-专业化-关系设计”。故事的要点是,这一定是第一个oc在我的网络生活中,标签在搜索中确实很有用。然而,我仍然希望听到你们的意见。

edit2:第二种方法的问题是,我预计大约有1000个专门化。有一个类别的层次结构(1-4层深),终端节点添加专门化变量-它们以1000的顺序累积,因此添加专门化的表来连接有点不切实际。

edit3:由于我的案例中存在大量的属性波动性,建议使用的“实体属性值”看起来是一条可行之路。查询噩梦来了!谢谢各位。

我一直在
Oracle
中这样做

我有以下表格:

t_class (id RAW(16), parent RAW(16)) -- holds class hierachy.
t_property (class RAW(16), property VARCHAR) -- holds class members.
t_declaration (id RAW(16), class RAW(16)) -- hold GUIDs and types of all class instances
t_instance (id RAW(16), class RAW(16), property VARCHAR2(100), textvalue VARCHAR2(200), intvalue INT, doublevalue DOUBLE, datevalue DATE) -- holds 'common' properties

t_class1 (id RAW(16), amount DOUBLE, source RAW(16), destination RAW(16)) -- holds 'fast' properties for class1.
t_class2 (id RAW(16), comment VARCHAR2(200)) -- holds 'fast' properties for class2
--- etc.
RAW(16)
Oracle
保存的
GUID
s

如果要选择对象的所有特性,请发出:

SELECT  i.*
FROM    (
        SELECT  id 
        FROM    t_class
        START WITH
                id = (SELECT class FROM t_declaration WHERE id = :object_id)
        CONNECT BY
                parent = PRIOR id
        ) c
JOIN    property p
ON      p.class = c.id
LEFT JOIN
        t_instance i
ON      i.id = :object_id
        AND i.class = p.class
        AND i.property = p.property
t_属性
保存通常不搜索的内容(如文本描述等)

事实上,Fast属性是数据库中的普通表,用于提高查询效率。它们只包含特定类或其子类的实例的值。这是为了避免额外的联接

您不必使用快速表并将所有数据限制在这四个表中

对于您的任务,它将如下所示(为了简洁起见,我将使用方括号中的字符串而不是GUID):

并使用它与其他属性联接,而不是在上面的查询中使用
t_声明


但是,即使没有快速表格,这种模式也是可行的。

您希望有多少种产品类型?它们各自有自己的应用逻辑吗

您可以创建一个称为“实体属性值”模型的通用模型,但当您试图处理产品的特定属性时,它会有很多陷阱。简单的搜索查询有时会变成真正的噩梦。基本思想是您有一个表,其中包含产品ID、属性名称(或属性表中的ID),和值。您还可以添加表来保存每种产品类型的模板。因此,一组表将告诉您任何给定产品的属性(可能还有有效的值范围),另一组表将告诉您任何单个产品的值

不过,我要强烈警告不要使用这个模型,因为在您必须实际实现它之前,它似乎是一个非常巧妙的想法


如果产品类型的数量受到合理限制,我会选择第二种解决方案—一个带有基本属性的主产品表,然后是每个特定产品类型的附加表。

此模式有一个名称。它被称为“泛化-专业化”


如果您搜索“泛化-专业化建模”“你会看到一些关于如何做到这一点的文章。其中一些文章倾向于关系建模和SQL,而另一些则倾向于对象建模

嗯,如果我理解正确的话-你做了我描述的第二种解决方案?每个专门化都有单独的表和额外的变量?只有当您需要提高性能时才会创建单独的表(我称之为fast pro)
SELECT  i.*
FROM    (
        SELECT  id 
        FROM    t_class
        START WITH
                id = (SELECT class FROM t_declaration WHERE id = :object_id)
        CONNECT BY
                parent = PRIOR id
        ) c
JOIN    property p
ON      p.class = c.id
LEFT JOIN
        t_instance i
ON      i.id = :object_id
        AND i.class = p.class
        AND i.property = p.property
t_class id parent [ClassItem] [ClassUnknown] [ClassMonitor] [ClassItem] [ClassLCD] [ClassMonitor] t_property class property [ClassItem] price [ClassItem] vendor [ClassItem] model [ClassMonitor] size [ClassLCD] matrixType t_declaration id class [1] [ClassLCD] -- Iiyama ProLite E1700 t_instance -- I'll put all values into one column, disregarding type (INT, VARCHAR etc) id class property value [1] [ClassItem] price $300 [1] [ClassItem] vendor Iiyama [1] [ClassItem] model ProLite E1700s [1] [ClassMonitor] size 17 [1] [ClassLCD] matrixType TFT t_lcd (id RAW(16), size INT, matrixType VARCHAR2(200)) id size matrixType [1] 17 TFT