假设我们有一个应用程序,它应该能够存储所有类型的产品。每个产品至少有一个ID和一个Name,但是所有其他属性都可以由用户自己定义。
您将如何根据上述需求对您的模式进行建模?
注:请求4.是重要的!
感谢大家的贡献和讨论的方法。我以前见过一些解决这个问题的办法,但没有一种办法使我容易分组:
发布于 2009-05-19 17:50:54
分组并不容易,因为您将在"color“上使用什么聚合运算符?请注意,不可能在第2种情况下使用您的需求4。
在任何情况下,聚合都是困难的,因为数据类型的变化,并且可以通过一种更典型的方式来减轻它--知道添加苹果和橘子是没有意义的。
这是典型的EAV模型,它在精心设计的数据库中占有一席之地。为了使其更具类型性,我看到了这样的情况:值存储在类型安全表中,而不是存储在一个自由形式的varchar列中。
而不是价值:
EntityID int
,AttributeID int
,Value varchar(255)您有多个表:
EntityID int
,AttributeID int
,ValueMoney money
EntityID int
,AttributeID int
,ValueInt int
etc.然后,要获得每一代的iPod容量:
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发布于 2009-05-19 18:16:51
我推荐混凝土表继承或类表继承的设计。这两种设计都符合你的四个标准。
在具体表继承中:
product_ipods中,列为ID、Name、Capacity、Generation。product_tshirts中,列为ID、Name、Size、Color。product_ipods和product_tshirts的元数据(表定义)中。SELECT SUM(Capacity) FROM product_ipods GROUP BY Generation;在类表继承中:
Products中,其中列为ID、Name。
Ipods存储在表product_ipods中,列为product_id (Products.ID的外键)、Capacity、Generation。product_tshirts中,其中列为product_id (Products.ID的外键)、Size、Color。products、product_ipods和product_tshirts的元数据(表定义)中。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,因为它只使用超级表生成的值。
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');发布于 2009-05-19 17:37:23
为新产品创建表,并在用户执行操作时通过添加/删除列来更改表。使用架构可以知道每个产品具有哪些属性。这满足了您的所有四个需求。
您还需要一个表来存储其他表的名称,或者在表的前面加上一些可以针对sysobjects查询表的内容:
select [name] from sysobjects where [name] like 'product_%' AND xtype='U'https://stackoverflow.com/questions/884050
复制相似问题