use*_*631 1 postgresql database-design relational-database
我有三个实体:项目、类别和属性。
AnItem可以是一个,也可以是多个Categories,因此存在 N:M 关系。
Item ItemCategories Categories
id name item_id category_id id name
1 alfa 1 1 1 chipset
1 2 2 interface
Run Code Online (Sandbox Code Playgroud)
根据它们所在的“类别”,可以Item有多个。Attributes
例如,Category“芯片组”中的项目可以具有以下属性:“接口”、“内存”、“技术”。
这些属性有一组不经常更改的预定义值,但它们可以更改。
例如:“内存”只能是 ddr2、ddr3、ddr4。
Attributes CategoryAttributes
id name values category_id attribute_id
1 memory {ddr2, ddr3, ddr4} 1 1
Run Code Online (Sandbox Code Playgroud)
Item“芯片组”中的Category可以访问该属性Attribute,并且只能具有 Null 或该属性的预定义值。
我想使用EnumorJson作为属性值,但我还有另外两个条件:
项目属性
item_id attribute_id value
1 1 {ddr2, ddr4}
Run Code Online (Sandbox Code Playgroud)
1) 如果一个属性出现在2个类别中,并且一个Ithe同时出现在两个类别中,则该属性只能显示一次。
2)我需要使用 的值rank,因此如果一个项目出现两个对应的属性值,如果只有一个,则排名应该更大,否则该值不存在。
3)为属性创建单独的表不是一个选项,因为数量不固定,并且可能很大。
因此,我不知道数据库设计中的最佳选择是限制值并用于订单排名。
您描述的问题是典型的开放模式或垂直数据库,这是某种EAV模型的经典用例。
EAV 是一个复杂而强大的范例,它允许潜在的开放模式,同时尊重数据库范式,并允许拥有您所需要的:根据同一实体的特定实例具有可变数量的属性。
这就是使用关系数据库的电子商务中通常发生的情况,因为不同的产品具有不同的属性(即口红有颜色,但对于硬盘驱动器来说,您可能不关心颜色而是关心容量),并且拥有一个没有意义属性表,因为数量不固定并且可能很大,并且对于大多数行来说,会有很多NULL值(这是稀疏矩阵的数学概念,在数据库表中看起来非常难看)
您可以查看Magento DB Model,这是大规模纯 EAV 的真正参考,或者Wikipedia,但您可能可以稍后再做,而现在,您只需要基础知识:
基本思想是将属性及其相应的值作为行而不是列存储在单个表中。
在更简单的实现中,表至少有三列:(entity通常是实体的外键,或实体类型/类别),attribute(这可以是字符串,或者在更复杂的系统中的外键)和value。
在我之前的示例中,过于简单化,我们可以有一个像这样的表,其中列出了属性名称及其值
Item table Attributes table
+------+--------------+ +-------------+-----------+-------------+
| id | name | | item_id | attribute | value |
+------+--------------+ +-------------+-----------+-------------+
| 1 | "hard drive" | | 2 | "color" | "red" |
+------+--------------+ +-------------+-----------+-------------+
| 2 | "lipstick" | | 2 | "price" | 10 |
+------+--------------+ +-------------+-----------+-------------+
| 1 | "capacity"| "1TB" |
+-------------+-----------+-------------+
| 1 | "price" | 200 |
+-------------+-----------+-------------+
So for every item, you can have a list of attributes.
Run Code Online (Sandbox Code Playgroud)
由于您的模型更复杂,有更多的约束,所以我们需要调整这个模型。
有了这个,你最终会得到类似的东西
类别表 类别 ID 和名称列表
+------+--------------+
| id | name |
+------+--------------+
| 1 | "chipset" |
+------+--------------+
| 2 | "interface" |
+------+--------------+
Run Code Online (Sandbox Code Playgroud)
属性表 属性 ID 及其名称的列表
+------+--------------+
| id | name |
+------+--------------+
| 1 | "interface" |
+------+--------------+
| 2 | "memory" |
+------+--------------+
| 3 | "tech" |
+------+--------------+
| 4 | "price" |
+------+--------------+
Run Code Online (Sandbox Code Playgroud)
类别-属性表 什么类别有什么属性。请注意,一个属性(即 4)可以属于 2 个类别
+--------------+--------------+
| attribute_id | category_id |
+--------------+--------------+
| 1 | 1 |
+--------------+--------------+
| 2 | 1 |
+--------------+--------------+
| 3 | 1 |
+--------------+--------------+
| 4 | 1 |
+--------------+--------------+
| 4 | 2 |
+--------------+--------------+
Run Code Online (Sandbox Code Playgroud)
值表 每个属性的可能值列表
+----------+--------------+--------+
| value_id | attribute_id | value |
+-------------+-----------+--------+
| 1 | 2 | "ddr2" |
+----------+--------------+--------+
| 2 | 2 | "ddr3" |
+----------+--------------+--------+
| 3 | 2 | "ddr4" |
+----------+--------------+--------+
| 4 | 3 |"tech_1"|
+----------+--------------+--------+
| 5 | 3 |"tech_2"|
+----------+--------------+--------+
| 6 | ... | ... |
+----------+--------------+--------+
| 7 | ... | ... |
Run Code Online (Sandbox Code Playgroud)
最后,你可以想象,
项目属性表将每行列出一个属性值
+----------+--------------+-------+
| item_id | attribute_id | value |
+----------+-----------+----------+
| 1 | 2 | 1 |
+----------+--------------+-------+
| 1 | 2 | 3 |
+----------+--------------+-------+
Meaning that item 1, for attribute 2 (`memory`), has values 1 and 3 (`ddr2` and `ddr3`)
Run Code Online (Sandbox Code Playgroud)
这将涵盖您的所有条件:
SELECT * from Category-Attribute where category_id in (SELECT category_id from ItemCategories where item_id = ...)为您提供符合条件的属性列表,即使 2 个类别具有相同属性,也只能显示其中一个)rank,我想我没有足够的信息来进行这个查询,但是这是一个完全标准化的模型,当然,你可以做一个排名。您在这里几乎拥有完整的模型,因此您肯定可以找出查询。这与 Magento 使用的模型非常相似。它非常强大,但当然,它可能会变得难以管理,但如果我们想要保持模型严格并确保它将强制执行约束并接受所有 SQL 函数,那么这是最好的方法。NoSQL对于不太严格的系统,选择具有更灵活模式的数据库始终是一个选择。