2010-05-20 90 views
4

我正在构建一个类似于here的数据库,其中我有不同类型的产品,每种类型都有其自己的属性。从子类中选择产品:我需要多少个查询?

我报告一个短版为了方便

product_type 
============ 
product_type_id INT 
product_type_name VARCHAR 

product 
======= 
product_id INT 
product_name VARCHAR 
product_type_id INT -> Foreign key to product_type.product_type_id 
... (common attributes to all product) 

magazine 
======== 
magazine_id INT 
title VARCHAR 
product_id INT -> Foreign key to product.product_id 
... (magazine-specific attributes) 

web_site 
======== 
web_site_id INT 
name VARCHAR 
product_id INT -> Foreign key to product.product_id 
... (web-site specific attributes) 

这样,我并不需要作出巨大的表,针对不同类型产品的每个属性的列(其中大部分,然后将NULL)

我如何SELECT一个产品product.product_id并查看其所有属性? 我是否必须首先进行查询以了解我正在处理的产品类型,然后通过某种逻辑对另一个查询JOIN正确的表格进行查询?或者有没有办法将所有的东西结合在一起? (如果当我检索有关product_id的信息时有很多NULL,那么在这一点上就没问题了)。

谢谢

回答

1

你可以做到这一切在一个查询中,一些列会留下空:

SELECT 
    t.product_type_name, 
    t.product_type_id 
    p.product_id, 
    p.product_name, 
    p.[common attributes to all products...], 
    m.*, 
    w.* 
FROM 
    product p 
    INNER JOIN product_type t ON t.product_type_id = p.product_type_id 
    LEFT JOIN magazine  m ON m.product_id  = p.product_id 
    LEFT JOIN web_site  w ON w.product_id  = p.product_id 
WHERE 
    p.product_id = ? 

使用product_type_id在您的应用程序,以确定哪些结果集的列是有趣的你在任何特定的情况下。

就性能而言,这应该运行得非常快(外键,索引);并为任何产品类型生成一致的结果集。

我建议不要使用.*并明确列出每个列的名称,这是更便携,更易于维护且不易出错。

+0

另外,使用w。*和m。*将重新包含您可能已包含的公共列。 – BradC 2010-05-20 16:58:18

+0

谢谢!有用。 我对SQL很新,我对LEFT JOIN的存在感到困惑。现在我明白了! 然而正确的方式大概是这样的: LEFT JOIN杂志M于m.product_id = p.product_id LEFT JOIN WEB_SITE W于w.product_id = p.product_id 由于PRODUCT_ID在产品表独特的,他们也在所有子表中都是唯一的,所以不需要magazine_id或web_site_id。 同样,我没有看到product_type表的需要。我可以在产品表中添加一个属性 – Stefano 2010-05-21 09:19:55

+0

@Stefano:1)我加入了'product_type',因为它在那里。 2)关于连接你是正确的,我使用了错误的列名。现在已经纠正了。 3)为什么你有*两个*属性来唯一标识一个杂志(显然是'magazine_id'和'product_id')?这种设置对我来说毫无意义。 'product_id'在不同产品类型中是唯一的,所以在每种产品类型中都不需要另一个唯一的ID。 – Tomalak 2010-05-21 12:06:49

0

何不做一个AttributeDefinition表和ProductAttribute表?沿着线的东西:

AttributeDefinition 
    Id 
    Description 

ProductAttribute 
    AttributeDefinitionId 
    ProductId 
    Value 

然后,无论哪种产品,你正在处理,你知道,你可以通过简单的查询ProductAttribute表中获取所有属性。每当需要使用具有自定义属性的新产品时,您不必添加新的特定表格。

2

不错的设计。干得好,避免了Entity Attribute Value陷阱。

您将按照您的建议简单地进行连接,但我不认为需要两个查询。我甚至不认为product_type表是必需的。

SELECT * FROM product p 
LEFT JOIN magazine m 
ON m.product_id = p.product_id 
LEFT JOIN web_site w 
ON w.product_id = p.product_id 

在上面的查询,为一家杂志社,m.product_id IS NOT NULL并为WEB_SITE,w.product_id IS NOT NULL。只有

杂志:只有

SELECT * FROM product p 
JOIN magazine m 
ON m.product_id = p.product_id 

网站:

SELECT * FROM product p 
JOIN web_site w 
ON w.product_id = p.product_id 

你最大的问题是如何取得的列名?你可能编码了这些,或者你使用反射来获得它们。大多数数据库访问层都提供反射

0

大讨厌的工会所有,每种类型明确列,NULL,如果他们不适用(大大简化):

SELECT ID, ProductType, m.Name as MagazineName, m.Pages as MagazinePages, 
         NULL as WebSiteName, NULL as WebSiteURL 
     FROM Magazines m 
UNION ALL 
SELECT ID, ProductType, NULL as MagazineName, NULL as MagazinePages, 
         w.Name as WebSiteName, w.URL as WebSiteURL 
     FROM WebSites w 

威尔产品等的输出:

ID Type  MagazineName MagazinePages WebSiteName WebSiteURL 
1 Magazine Time   100    NULL   NULL 
2 Magazine Newsweek  80    NULL   NULL 
3 Website NULL   NULL   Yahoo   www.yahoo.com 
4 Website NULL   NULL   Google  www.google.com