我有三张桌子:
blog_posts
int id (auto increment)
varchar(255) title
text content
blog_tags
int id (auto increment)
varchar(63) name
blog_posttags
int id (auto increment)
int post_id
int tag_id
如何获得(最好是尽可能少的查询)这些数据,如具有以下结构的多维数组?
我可以弄清楚如何从数据库中创建数组,但不知道如何在不查询我收到的每个博文来查看哪些标签属于它的情况下完成这样的操作。
$blogposts = array(
array(
'id' => 0,
'title' => 'blogpost title',
'content' => 'blogpost content',
'tags' => array(
'tagname1', 'tagname2', 'tagname3', ...,
)
),
... (multiple blogposts because WHERE condition may return more than 1)
)
我想我必须使用UNION
或JOIN
或类似的东西,但我对高级MySQL语句并不熟悉。
修改:您可能会认为tag_id
中的blog_posttags
也存在于blog_tags
中,post_id
和blog_posts
也是如此。
答案 0 :(得分:2)
您可以使用MySQL GROUP_CONCAT
函数获取单个查询中的所有标记:
SELECT a.id
,a.title
,a.content
,( SELECT GROUP_CONCAT(b.name)
FROM blog_tags b
JOIN blog_posttags c
ON b.id = c.tag_id
WHERE c.post_id = a.id
) AS tags
FROM blog_posts a
将连接标签,如:
id title content tags
-------------------------------------------
1 Blog 1 blah blah blah funny,work
2 Next Post yadda yadda school,work
返回如下数组:
$blogposts = array(
array(
'id' => 0,
'title' => 'blogpost title',
'content' => 'blogpost content',
'tags' => 'tagname1,tagname2,tagname3'
),
//etc
);
然后你只需要像这样运行一个循环来分割逗号分隔的标记字符串
foreach($blogposts as $k => $v){
$blogposts[$k]['tags'] = explode(',', $v['tags']);
}
以下是示例SQL Fiddle,其中包含一些虚拟标记和帖子,我曾在发布
之前对其进行测试修改强>
以下是在不使用子查询的情况下实现相同结果的另一种方法:
SELECT a.id
,a.title
,a.content
,GROUP_CONCAT(c.name) AS tags
FROM blog_posts a
JOIN blog_posttags b
ON a.id = b.post_id
JOIN blog_tags c
ON b.tag_id = c.id
GROUP BY a.id
答案 1 :(得分:0)
获取与帖子匹配的标签信息的基本查询将如下所示。
Select bp.Id, bp.title, bp.content, bt.name
from blog_posts bp
JOIN blog_posttags bpt ON bp.Post_id = bpt.post_id
JOIN blog_tags bt ON bt.tag_id = bpt.tag_id
这将为您提供多行,每行匹配一个帖子到一个标签。将标记分组到数组中并不是您可以在SQL端执行的操作,但您可以执行
Select bt.name
from blog_posts bp
JOIN blog_posttags bpt ON bp.Post_id = bpt.post_id
JOIN blog_tags bt ON bt.tag_id = bpt.tag_id
WHERE bp.Id = 12345
作为单独的查询来获取给定帖子的标记。在这两者之间,您应该能够在应用程序级别创建嵌套数组。