2012-02-24 26 views
3

讓我們假設您正在創建一個系統來存儲不同國家的特徵。會有相同的基本列如名稱,人口,首府城市等。但讓我們說,除此之外,你想存儲一些國家的具體信息,如最高的山峯,最近的海洋,最着名的食物等。這些列將有所不同國家。如何在表中使用不同數量的列來設計數據庫

這是如何使用像MySQL這樣的關係數據庫來完成的。 我知道使用像MongoDB這樣的無模式的NoSQL數據庫更容易,每個國家/地區都可以作爲單獨的文檔存儲。但是可以使用關係數據庫來完成這樣的事情嗎?

+1

您必須創建2個附加表。首先是項目列表('id,title')=(1,'Highest mountain'),第二個表用於存儲國家的值 - ('itemId,countryId,value') – teran 2012-02-24 16:22:07

+0

@gaurav: t認爲標籤nosql適用於rdbms相關問題... – 2012-02-24 16:28:19

+0

@iDevlop - 謝謝,我刪除了nosql標籤。 – gaurav 2012-02-24 16:57:39

回答

4

只顯示文本字段,你需要兩個額外的表:

  • 屬性(包含一個屬性,如「最高的山」的名稱)
  • country_properties(包含值國別屬性對:例如:國家「奧地利」的ID,財產「最高的山」,「山的名字」的ID)

或者,如果只有幾個屬性,簡單地存儲NULL爲未知值。

+0

如果您也有整數或浮點值,您可以在'properties'表中存儲'fieldType'列,然後您可以將3列添加到'values'表中作爲(propId,countryId,charValue,intValue,floatValue) – teran 2012-02-24 16:48:29

0

你真的不應該這樣做,與標準的關係數據庫。而應將額外的數據存儲在單獨的表中,並使用引用國家/地區表的外鍵。

僅有時使用的列通常違反關係完整性。有時候,由於性能原因,這是必要的,但如果這不是您的問題,我會強烈建議使用最合適的關係模型。

3

它可以。正如我今天通過詢問another question on SO所瞭解到的那樣,這被稱爲EAV(用於實體屬性值模型)。我在wikipedia上發現了一個有趣的解釋。

+1

+1 EAV。 – 2012-02-24 18:26:16

0

如果列是每個國家真正的不同,然後創建一個有以下的列

  • COUNTRY_ID(FK貴國表)
  • FIELD_NAME VARCHAR
  • FIELD_VALUE VARCHAR
  • country_field稱爲新表

將您所在國家/地區特定的屬性存儲在此表中,每個國家/地區特定字段包含一行。

0

我有需要MySQL的,我發現最flexable的選擇對我們來說是分割的數據到多個表的應用程序類似的場景,例如我們可能有一個表稱爲country_register

country_id (int primary key) | country_name 

然後我們所謂另一個表說country_data

tbl_id (int primary key) | country_id (int foreign key) | country_property (varchar index) | country_data (text indexed as fulltext) 

基本上country_property是一個參考,你得到的數據出來,所以它可能是如「人口」和country_data然後會有你想要的實際數據。

然後,您將使用JOIN,並且每一行都會包含所有您需要的數據。這是使用我所知道的mySQL最靈活的結構,並且適用於這些類型的任務。

我希望這會有所幫助。

0

讓我們山區爲例:

CREATE TABLE `countries` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `name` VARCHAR(255), 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `mountains` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `country_id` INT(11) UNSIGNED NOT NULL, 
    `name` VARCHAR(255), 
    `height` INT(10) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `fk_country_id` (`country_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

可以比創建一個SELECT - 查詢,讓每個國家的最高的山,通過執行類似:

SELECT c.name, m.name, MAX(m.height) as height 
FROM mountains m 
JOIN countries c 
ON c.id = m.country_id 
GROUP BY m.country_id; 
+0

你會爲每個實體創建單獨的表嗎?山,河,海洋,食物等? 如果你只有很少的實體,這是一個很好的方法..但在這種情況下它不是。恕我直言。 – teran 2012-02-24 16:41:48

+0

我不想投這個票,但在我看來這個設計非常糟糕。我知道這是一個老話題,但如果像我這樣的人後來發現這個具體的答案:不要這樣做。 – 2012-06-25 04:52:32

+0

@MichaelOzeryansky:向我們展示爲什麼你認爲這種設計不好,也許是個好主意。我也喜歡從我的錯誤中學習。 – 2012-06-25 05:39:56

0

什麼你所描述的是一個超級類型 * 子類型 *的數據結構。 Super-Type是所有數據中的常見現象(在您的國家/地區)。 子類型是每組數據(在您的案例國家/地區)唯一的。你會有一個超級類型的表和**幾個子類型表。子類型表包含鏈接回超類型表的FKeys。

這可讓您通過超強型查詢所有,然後通過分型做了向下鑽取。浮現在腦海中的國家

* 強大的文本 *子類型是:
Mountanous
內陸
海景

你甚至可以子出來的大陸: 北美洲
南美洲
亞洲
大洋洲

0

這裏我們有三種策略:

  1. 完全元設計,國家的可空屬性的值將被放入價值收集表。例如:

    country(country_id,non-null-attr-1,non-null-attr-2,non-null-attr -....) meta_attr(attr_id,attr_desc)(if more complex if你需要I18N) attr_value(country_id,attr_id,attr_value)

  2. 部分元設計,使用表的子類引用國家的主表。如果可以將某個數據實例歸類爲非空屬性的集合,則此方法可用。例如:

    country(country_id,non-null-attr-1,non-null-attr-2,non-null-attr -....) specific_type_country(country_id,non-null-attr-1 ,非null-attr-2,non-null-attr -...)

  3. 國家主表中的所有屬性,只有當您不需要將新屬性添加到國家/地區時,此方法纔可行系統。例如:

    country(country_id,non-null-attr-1,non-null-attr-2,non-null-attr -....,nullable-attr-1,nullable-2,nullable- attr -...)

當我在這樣的場景下設計時,我曾經考慮過在這樣的數據上運行的查詢的性能。

如果查詢是所有可能屬性的國家/地區列表,則使用No.3更好。

如果查詢針對的是某個類別的國家,比如說一個國家/地區列表中有最近的海洋(該屬性不能爲空)。 2號更好。

如果查詢一次需要某個國家的詳細信息,則No.1爲好。

當然,您可以混合上述三種策略中的任何一種來爲您的可能查詢設計合適的解決方案。


假設任何查詢都需要「最着名的食物」(可爲空),將該屬性放在國家的主表中。

假設在一些查詢中需要「最近的海洋」,將該屬性放入國家表的子類中。

假設最多隻檢索一行的查詢(比如說,通過主鍵查詢)需要「最高山峯名稱」,「最高山峯的平均溫度」,則將該屬性放入元表中。

相關問題