首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何对实体的自定义属性进行建模?

如何对实体的自定义属性进行建模?
EN

Stack Overflow用户
提问于 2009-05-19 17:24:36
回答 5查看 9.9K关注 0票数 6

假设我们有一个应用程序,它应该能够存储所有类型的产品。每个产品至少有一个ID和一个Name,但是所有其他属性都可以由用户自己定义。

  1. 例如,他可以创建一个包含属性、容量和生成的产品组Ipods。
  2. 例如,他可以创建一个具有属性大小和颜色的产品组TShirts。
  3. 我们需要存储产品的定义和具体产品本身。
  4. 我们希望确保能够轻松地按产品属性聚合(分组)。例如,选择每一代ipods的总容量和
  5. 解决方案必须不需要模式更改(由于Bill的输入而增加了需求-参见他的答案!)

您将如何根据上述需求对您的模式进行建模?

注:请求4.是重要的!

感谢大家的贡献和讨论的方法。我以前见过一些解决这个问题的办法,但没有一种办法使我容易分组:

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-05-19 17:50:54

分组并不容易,因为您将在"color“上使用什么聚合运算符?请注意,不可能在第2种情况下使用您的需求4。

在任何情况下,聚合都是困难的,因为数据类型的变化,并且可以通过一种更典型的方式来减轻它--知道添加苹果和橘子是没有意义的。

这是典型的EAV模型,它在精心设计的数据库中占有一席之地。为了使其更具类型性,我看到了这样的情况:值存储在类型安全表中,而不是存储在一个自由形式的varchar列中。

而不是价值:

代码语言:javascript
运行
复制
EntityID int
,AttributeID int
,Value varchar(255)

您有多个表:

代码语言:javascript
运行
复制
EntityID int
,AttributeID int
,ValueMoney money

EntityID int
,AttributeID int
,ValueInt int

etc.

然后,要获得每一代的iPod容量:

代码语言:javascript
运行
复制
SELECT vG.ValueVarChar AS Generation, SUM(vC.ValueDecimal) AS TotalCapacity
FROM Products AS p
INNER JOIN Attributes AS aG
    ON aG.AttributeName = 'generation'
INNER JOIN ValueVarChar AS vG
    ON vG.EntityID = p.ProductID
    AND vG.AttributeID = aG.AttributeID
INNER JOIN Attributes AS aC
    ON aC.AttributeName = 'capacity'
INNER JOIN ValueDecimal AS vC
    ON vC.EntityID = p.ProductID
    AND vC.AttributeID = aC.AttributeID
GROUP BY vG.ValueVarChar
票数 5
EN

Stack Overflow用户

发布于 2009-05-19 18:16:51

我推荐混凝土表继承类表继承的设计。这两种设计都符合你的四个标准。

在具体表继承中:

  1. Ipods存储在表product_ipods中,列为IDNameCapacityGeneration
  2. T恤被存储在表product_tshirts中,列为IDNameSizeColor
  3. 具体产品类型的定义在product_ipodsproduct_tshirts的元数据(表定义)中。
  4. SELECT SUM(Capacity) FROM product_ipods GROUP BY Generation

在类表继承中:

  1. 通用产品属性存储在表Products中,其中列为IDName。 Ipods存储在表product_ipods中,列为product_id (Products.ID的外键)、CapacityGeneration
  2. T恤被存储在表product_tshirts中,其中列为product_id (Products.ID的外键)、SizeColor
  3. 具体产品类型的定义在productsproduct_ipodsproduct_tshirts的元数据(表定义)中。
  4. SELECT SUM(Capacity) FROM product_ipods GROUP BY Generation

还请参阅我对"产品表,产品种类繁多,每种产品都有很多参数。“的回答,其中我描述了您所描述的问题类型的几个解决方案。我还详细介绍了为什么EAV是一个失败的设计.

关于@dcolumbus的评论:

对于CTI,product_ipods的每一行都会随其自身的价格而变化吗?

如果每种类型的产品都有价格,我希望价格列出现在products表中。对于CTI,产品类型表通常只包含仅与该类型产品相关的属性列。所有产品类型共有的任何属性都会在父表中获取列。

另外,在存储订单行项时,您会将product_ipods中的行作为行项存储吗?

在行项表中,存储产品id,它应该在products表和product_ipods表中都是相同的值。

关于@dcolumbus的评论:

对我来说是多余的..。在这种情况下,我看不出子表的意义。但是,即使子表确实有意义,连接的id是什么?

子表的重点是存储所有其他产品类型不需要的列。

连接id可以是自动增量号。子类型表不需要自动增加自己的id,因为它只使用超级表生成的值。

代码语言:javascript
运行
复制
CREATE TABLE products (
  product_id INT AUTO_INCREMENT PRIMARY KEY,
  sku VARCHAR(30) NOT NULL,
  name VARCHAR(100) NOT NULL,
  price NUMERIC(9,2) NOT NULL
);

CREATE TABLE product_ipods (
  product_id INT PRIMARY KEY,
  size TINYINT DEFAULT 16,
  color VARCHAR(10) DEFAULT 'silver',
  FOREIGN KEY (product_id) REFERENCES products(product_id)
);

INSERT INTO products (sku, name, price) VALUES ('IPODS1C1', 'iPod Touch', 229.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 16, 'silver');
INSERT INTO products (sku, name, price) VALUES ('IPODS1C2', 'iPod Touch', 229.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 16, 'black');
INSERT INTO products (sku, name, price) VALUES ('IPODS1C3', 'iPod Touch', 229.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 16, 'red');
INSERT INTO products (sku, name, price) VALUES ('IPODS2C1', 'iPod Touch', 299.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 32, 'silver');
INSERT INTO products (sku, name, price) VALUES ('IPODS2C2', 'iPod Touch', 299.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 32, 'silver');
INSERT INTO products (sku, name, price) VALUES ('IPODS2C3', 'iPod Touch', 299.00);
INSERT INTO product_ipods VALUES (LAST_INSERT_ID(), 32, 'red');
票数 11
EN

Stack Overflow用户

发布于 2009-05-19 17:37:23

为新产品创建表,并在用户执行操作时通过添加/删除列来更改表。使用架构可以知道每个产品具有哪些属性。这满足了您的所有四个需求。

您还需要一个表来存储其他表的名称,或者在表的前面加上一些可以针对sysobjects查询表的内容:

代码语言:javascript
运行
复制
select [name] from sysobjects where [name] like 'product_%' AND xtype='U'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/884050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档