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