MySQL如何组合这些表?

时间:2013-11-27 00:39:13

标签: php mysql multidimensional-array

我有三张桌子:

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)
)

我想我必须使用UNIONJOIN或类似的东西,但我对高级MySQL语句并不熟悉。

修改:您可能会认为tag_id中的blog_posttags也存在于blog_tags中,post_idblog_posts也是如此。

2 个答案:

答案 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

作为单独的查询来获取给定帖子的标记。在这两者之间,您应该能够在应用程序级别创建嵌套数组。