2012-03-19 84 views
1

我工作的一個標籤的功能,這是我的數據庫結構至今:標籤功能 - 兩個表(3NF)之間的關係存儲

`tags` Table:  `content` Table: 

id | tagname  id | title  | tags 
------------  ----------------------- 
1 | fire   1 | Charizard | 1 3 
2 | water   2 | Blastoise | 2 
3 | flying   3 | Charmander | 1 

什麼是使用這兩個表和輸出的最佳方法每項內容的正確標籤? 如果我以這種方式呼籲我的標籤:

$query = mysql_query("SELECT * FROM `content`"); 

while ($tableData = mysql_fetch_array($query)) { 
    echo $tableData["tags"]; 
} 

這顯然輸出的原始文本內容分別1 321。 我希望它分別顯示fire flyingwaterfire

我應該如何使用內容表中的標籤列給出的信息來獲取這些標記名?

+3

你真的需要第三張關係表。 'tags_content'與'id 1 tag 1,id 1 tag 3,id 2 tag 2'等。 – Interrobang 2012-03-19 05:04:32

+2

在一個字段中存儲多個值不是好習慣。你應該學習規範化。 – 2012-03-19 05:11:03

回答

2

是的,你應該研究規範化並將你的表格改爲3NF。首先,這將爲您節省一些令人頭痛的問題,其次,正常化非常酷。這裏有一個非常快速的總結,你會做什麼:

讓你所有的標籤在一個領域是不好的做法。這意味着所有將查詢數據庫的內容都必須確切知道你如何存儲它們以及如何將它們分開。這也意味着你將無法使用純SQL來提問諸如「有多少口袋妖怪有火屬性」或「哪個標籤最受歡迎」等問題,因爲SQL不知道你的空格分隔的標籤列表手段。相反,您會將content分爲兩個表格:monstersattributes。怪物看起來是這樣的:

id | name 
---|--------- 
1 |Charizard 
2 |Blastoise 
... 

和屬性看起來是這樣的:

monsterid | tagid 
----------|---------- 
     1 | 1 
     1 | 3 
     2 | 2 
... 

爲了得到一個怪物的屬性,你會發現它在怪物表名,獲得其ID,並使用其ID查找它的屬性來自屬性表。這是使用JOIN的微不足道的,它爲您提供了大量的權力來以有趣的方式檢索您的信息。

要回答你原來的問題,你會做這樣的事情:

SELECT monsters.id as monsterid, monsters.name, tags.tagname from monsters 
    INNER JOIN attributes ON (monsters.id = attributes.monsterid) 
    INNER JOIN tags ON (tags.id = attributes.tagid) 
    ORDER BY monsters.id 

而且你會得到一個結果表看起來像這樣:

monsterid | name  | tagname 
----------|-----------|-------- 
     1 | charizard | fire 
     1 | charizard | flying 
     2 | blastoise | water 
.... 

然後你可以遍歷被返回,行這樣做:

$monsters = array(); 
while ($tableData = mysql_fetch_array($query)) { 
    $monstername = $tabledata['name']; 
    if(!isset($monsters[$monstername])) { $monsters[$monstername] = array(); } 
    $monsters[$monstername][] = $tabledata['tagname']; 
} 

然後最後你會公頃ve你想要什麼,一個數組中的每個元素都由一個怪物的名字來標識,而這個數值是一個包含所有怪物標籤的數組。


...說真的,我知道比你最初問這個聽起來hellishly複雜,但我認爲這是做這不太可能在你的臉炸燬最簡單的方法。希望有人會糾正我,如果我錯了。

警告 - 這裏的代碼被寫在我頭上。它可能有一些錯誤,但它應該告訴你如何實現解決方案。

1

這裏,@Interrobang說,最好的辦法是實行3NF

所以,你需要創建存儲標籤和內容

content_tags(id,content_id,tag_id). 

其中的content_id,TAG_ID是關係一個新的表resp選項卡的主鍵。

以下3NF會讓你輕鬆刪除和更新。 比如:以後,會有如需要一個標籤3從內容1

If u have applied 3NF, you can easily find the specific record and delete it 
whereas 
if it was stored space or comma separated then you need to fetch using string func then not to forget the previous value(1,3) remove 3 again store the string 3. 

3NF will be useful for tag search too. 

刪除例如: 對於內容1 reationship將被存儲爲FOLL:

id | content_id | tag_id 
--------------------------------- 
1 | 1  | 1 
2 | 1  | 3 

後來,

select content.id,content,tags 
from content inner join on content_tags on (content.id = content_tags.content_id) 
inner join tags on (content_tags.tag_id = tags.id) 
+0

非常好,謝謝。 – Aaron 2012-03-19 05:15:51