从子类中选择产品:我需要多少个查询?

时间:2010-05-20 16:42:24

标签: sql mysql database-design

我正在构建一个类似于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,那么此时就可以了。)

谢谢

4 个答案:

答案 0 :(得分:2)

漂亮的设计。避免实体属性值陷阱的好工作。

您只需按照建议进行加入,但我认为不需要进行两次查询。我甚至不认为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

你最关心的问题是获取列名?你可能正在对这些进行编码,或者你使用反射来获取它们。大多数数据库访问层都提供反射。

答案 1 :(得分: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来确定在任何特定情况下您对结果集的哪些列感兴趣。

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

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

答案 2 :(得分:0)

为什么不制作AttributeDefinition表和ProductAttribute表?有点像:

AttributeDefinition
    Id
    Description

ProductAttribute
    AttributeDefinitionId
    ProductId
    Value

然后,无论您正在处理哪种产品,您都知道只需查询ProductAttribute表即可获得所有属性。每当需要具有自定义属性的新产品时,您就不必添加新的特定表。

答案 3 :(得分:0)

Big nasty union all,每个类型都有显式列,如果它们不适用则为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