关于文章标签CURD的数据库设计

现在用的是文章标签三张表设计:posts,tags,relationships,但有一个问题是:
在一个页面内列出N篇文章的信息和对应的标签,我的做法是
1、根据指定条件先从POSTS表中取出N篇文章的信息
2、再根据1中得到的POSTID从TAGS中关联取出对应标签
那么就是列出N篇文章,为了得到每篇文章对应的标签就要再执行N次数据查询
这个算是问题吗?大家如何做的?

阅读 12.5k
5 个回答

你想得到的是:

1、文章列表
2、文章列表中,每篇文章对应的tags

我建议你通过3条SQL来完成:

1、获得文章列表

SELECT * FROM `posts`

2、获得文章tags id

SELECT `post_id`,`tag_id` FROM `relationships` WHERE `post_id` IN (...)

建议存入post_id => tag_ids数组,如

$post_tags = array(
  1=>array(1,2,3),
  2=>array(2,3,5),
);

3、将用到的tag存入数组

SELECT `id`,`tag` FROM `tags` WHERE `id` IN (...)

得到id=>tag

$tags = array(
  1=>'火车',
  2=>'飞机',
);

4、遍历文章列表,并根据tags列表,对tags进行输出
最后:

诸如tags表,建议采用keyvalue数据库进行存储,如memcached、tokyo cabinet、redis等
诸如relationships表,建议复制一份到posts表,以text 1,2,3,4这样的形式存储。relationships表主要用于根据tag对文章进行检索用

是的,你最好连续两次left join relations表和tags表来减少sql语句的数量

from语句这么写

from posts as p 
left join relations as r on r.pid = p.id
left join tags as t on t.id = r.tid

@Chris Yue
如果每篇文章对应有N个标签,那么两次join后对于结果集中文章表的重复数据如何过滤?用GROUP BY + GROUP_CONCAT()的方式吗?还是在程序中对结果集用循环处理?

文章1, 标签N
文章1, 标签N
文章1, 标签N
文章2, 标签N
文章2, 标签N
文章2, 标签N
……
文章N, 标签N
文章N, 标签N
文章N, 标签N

如何将上面的结果集变成下面这样:

文章1, 标签N, 标签……, 标签N
文章2, 标签N, 标签……, 标签N
……
文章N, 标签N, 标签……, 标签N

仅仅是为了获取标签吗?
做个标签表, 标签数据全部缓存
post中加一taglist, 为关联的标签id逗号间隔

获取时分别从缓存中取就行了
这个方案复杂点的就是标签的增改了, 不过也没大难度

如果要获取标签关联的post列表, 可以一样的在tag表中加一个postlist字段

新手上路,请多包涵

最好还是post中加一个字段名字叫tag,当对文章标签增删改查的时候更新tag字段,tag字段存放tag id和name的二维数组的序列化或者json。这样每次取的时候直接解析tag字段就行了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题