考虑我有这种情况:
users
表
| id | name |
|----|------|
| 1 | Joe |
attributes
表
| id | name |
|----|--------|
| 1 | Age |
| 2 | Height |
| 3 | Gender |
client_attribute
表
| id | client_id | attribute_id | value |
|----|-----------|--------------|-------|
| 1 | 1 | 1 | 45 |
属性可以扩展到数百个变体。查询用户并选择“常见”属性列时,例如“年龄”:
我的代码应该采用属性的名称还是ID?如果不是,是否应将通常访问的属性直接放在users
表上?如果这些通用属性继续扩展该怎么办?
我的查询可能会选择不同区域中的两个或三个属性,我发现此表设计使事情变得困难(但我可以看到它的参数)。
答案 0 :(得分:1)
给出的说明实际上并不是实体之间的“多对多”关系。
显示的表是典型的EAV(实体-属性-值)实现的说明。
问:我的代码应采用属性的name
还是id
?
A:通常,SQL将按attribute
引用id
行。但是我们也可以使用name
列。通常,应用程序代码将处理“选定”属性的转换。 (我们将需要研究一些示例进行说明。)
问:如果不是,是否应将常用属性直接放在用户表上?
A:传统的关系模型在实体上只有一行(例如user
表中的一行),每个属性都有单独的一列:名字,姓氏,性别,出生日期,高度等
问:如果这些通用属性继续扩展该怎么办?
在传统的关系模型中,我们将添加其他列(DDL ALTER TABLE操作。对于EAV模型,我们不需要添加列,我们将向attribute
表中添加行(DML INSERT操作)。
EAV模型更为复杂,因为属性值不存储在实体行中,而是作为单独表中的行存储,就像我们对多值属性的存储一样。您注意到,EAV既有优点,也有明显的缺点。
问:我的查询可能会选择不同区域的两个或三个属性,而我发现这种表设计会使事情变得困难
A:真正的复杂性(和性能问题)是在试图纠缠EAV模型以返回行的时候出现的,就像我们回到传统的关系模型中一样;如果我们尝试编写一个查询,该查询返回的行看起来像是来自user
表的行,并且每个属性都有单独的列。
如果我们进行EAV,那么我们应该进行完整的EAV,而不是尝试编写返回结果集看起来像来自关系模型的SQL的SQL。可能,但是查询变得复杂。
此外,我不会存储“ age”属性,因为该属性会随时间而变化;一个人的年龄是当前日期和出生日期之间的差。
对于初学者来说,EAV模型具有很大的灵活性和易用性。这种灵活性是有代价的。考虑如何处理属性的各个域。名字和姓氏字符串可以存储为VARCHAR,但是某些属性可以是日期,十进制,整数。我们是将所有属性存储为VARCHAR,还是应该有多个列,然后使用某种区分符告诉我们应从中提取该属性的数据类型列。
答案 1 :(得分:0)
您可以使用复选框来选择“属性”,其值将是ID,在查询中,您将使用“ WHERE attributes in ("$variable")
$ variable将包含您要选择的所有ID。
答案 2 :(得分:0)
我的代码应该采用属性的名称还是id?
最好对联接和名称使用PK /索引,但基本上两者都可以工作,只是对性能的影响很小。
如果没有,应该将常用属性放置在用户身上 桌子直接?如果这些通用属性继续扩展该怎么办?
在检索所需数据的任何子集时,我没有发现您提供的设计有任何问题或出现任何复杂问题。
1)检索所有用户和属性信息:
SELECT A.name, C.name, B.value FROM users A
JOIN client_attribute B ON A.id = B.client_id
JOIN attributes C ON B.attribute_id = C.id
输出:
Joe Age 45
Joe Height 5
Joe Gender Male
Michelle Age 23
Michelle Height 4
Michelle Gender Female
2)检索特定属性ex。年龄:
SELECT A.name, C.name, B.value FROM users A
JOIN client_attribute B ON A.id = B.client_id
JOIN attributes C ON B.attribute_id = C.id
where C.name = 'Age';
最好使用id:
SELECT A.name, C.name, B.value FROM users A
JOIN client_attribute B ON A.id = B.client_id
JOIN attributes C ON B.attribute_id = C.id
where C.id = 1;
输出:
Joe Age 45
Michelle Age 23
3)检索特定用户的信息:
SELECT A.name, C.name, B.value FROM users A
JOIN client_attribute B ON A.id = B.client_id
JOIN attributes C ON B.attribute_id = C.id
where C.id = 1 AND A.name = 'Joe';
或使用ID:
SELECT A.name, C.name, B.value FROM users A
JOIN client_attribute B ON A.id = B.client_id
JOIN attributes C ON B.attribute_id = C.id
where C.id = 1 AND A.id = 1;
输出:
Joe Age 45
我的查询可能会选择不同区域中的两个或三个属性, 我发现此表设计使事情变得困难(但我可以看到 的参数)。
不太确定查询的意思是可以在不同区域中选择两个或三个属性,基本上可以编写查询以根据需要指定任何目标数据子集。希望以上内容能对您有所帮助,如果我错过了让我知道的事情。