我正在尝试实现一个简单的标记系统(在php中搞乱)......
我使用以下sql命令获取所需的线程,其作者以及与之关联的标记:
$thread = select_Query("SELECT thread.title, thread.id as t_id,
thread.content, author.username, author.id as a_id,
GROUP_CONCAT(DISTINCT tags.name ORDER BY tags.name DESC SEPARATOR ',') AS tags
FROM thread JOIN thread_tags ON thread.id = thread_tags.thread_id
JOIN tags ON thread_tags.tag_id = tags.id
INNER JOIN author on author.id = thread.author_id
WHERE thread.id = $id", $link);
如您所见,我正在使用GROUP_CONCAT。这工作正常,但是当我这样做时,标签都出现在一个变量中,我知道我可以使用$pieces = explode(",", $thread['tags]);
但是有另一种方法吗?我问这个是因为标签很容易分开但是如果它更复杂(例如包含分隔符的东西)。
我的数据库架构如下:
thread:id,content,title,author_id
thread_tags:id,tag_id,thread_id
标签:id,name
答案 0 :(得分:2)
您可以将GROUP_CONCAT
使用的分隔符更改为不会出现在代码中的内容,也可以是“|”字符。
GROUP_CONCAT(DISTINCT tags.name ORDER BY tags.name DESC SEPARATOR '|')
您还可以验证标记字段,并确保它不包含分隔符。
答案 1 :(得分:1)
大多数标记系统对标记中哪些字符可以或不可以有一组固定的要求。你可以在你的标签中禁用,
个字符,它可以正常工作。
答案 2 :(得分:1)
不要试图将多个值压缩到单个单元格中。这不是SQL的设计使用方式,正如您正确指出的那样,如果您的分隔符显示为其中一个值,则可能会导致问题。
幸运的是,有一种方法可以通过重写您的查询来解决这个问题。解决方案是在单元格中返回多行而不是多个值。实际上,您规范化结果集。
换句话说,而不是:
1 tag_1,tag_2,tag_3
2 tag_2,tag_4,tag_5
这样做:
1 tag_1
1 tag_2
1 tag_3
2 tag_2
2 tag_4
2 tag_5
天真地执行此操作可能会导致其他列重复相同的值,如果这些列可能包含大量数据,则可能会浪费不必要的带宽。解决方法是使用两个查询。
换句话说,而不是:
1 foo bar tag_1
1 foo bar tag_2
1 foo bar tag_3
2 baz qux tag_2
2 baz qux tag_4
2 baz qux tag_5
这样做:
Result 1:
1 foo bar
2 baz qux
Result 2:
1 tag_1
1 tag_2
1 tag_3
2 tag_2
2 tag_4
2 tag_5
现在您的结果集处于正常状态。另请注意,您不再需要运行DISTINCT操作,因为结果已经不同。事实上,这两个查询与原始数据库表更加匹配,因此查询可以更简单,并且运行速度更快。