2012-03-19 87 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