2010-05-20 35 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