连接行的最有效方法

时间:2014-10-11 15:50:37

标签: mysql group-by relational-database aggregate-functions group-concat

我的SQL知识确实有点生疏,但对于专家来说,我有一个简单的问题。我有三张桌子:

帖子   - post_id  - 名称   - 说明

posts_categories   - post_id   - slug

posts_themes   - post_id   - slug

基本上我想查询一下这样的帖子:

SELECT post_id, name, description, themes, categories FROM posts LIMIT 0, 50

我想结合相关的类别&主题表并将它们连接成一个列。所以我的输出是:

1 |测试|描述|音乐,艺术,历史|重要的是,相关的,新

我已尝试将此作为子查询,但遇到了返回多行的常见问题。我也尝试过LEFT JOIN&#39结果,但我似乎无法获得正确的结果。由于害怕在没有意识到的情况下弄错我的结果,我希望有人可以帮助制定最有效和最正确的查询。

感谢。

2 个答案:

答案 0 :(得分:1)

从主表(帖子)开始,您可以与主题和类别表进行常规连接。在这种情况下使用左连接以允许没有类别或主题的行显示在结果中。

要获取逗号分隔值,您可以按posts(每行应该有一个值)的值进行分组,并使用GROUP_CONCAT()逗号分隔非分组值,例如;

SELECT p.post_id, p.name, p.description,
   COALESCE(GROUP_CONCAT(pc.slug), '') categories,
   COALESCE(GROUP_CONCAT(pt.slug), '') themes
FROM posts p
LEFT JOIN posts_categories pc ON p.post_id = pc.post_id
LEFT JOIN posts_themes pt ON p.post_id = pt.post_id
GROUP BY p.post_id, p.name, p.description
ORDER BY p.post_id, p.name, p.description
LIMIT 50

An SQLfiddle to test with

答案 1 :(得分:0)

您是GROUP_CONCAT()未来满意的客户。

考虑这个子查询:

SELECT post_id, GROUP_CONCAT(slug) AS slugs
  FROM posts_categories
 GROUP BY post_id

它将通过邮件为您提供逗号分隔的类别slug列表。类似的查询将为您提供主题slugs。

然后,您只需加入这些子查询即可。

SELECT a.post_id, a.name, a.description,
       b.slugs AS categories,
       c.slugs AS themes
  FROM posts AS a
  LEFT JOIN (
          SELECT post_id, GROUP_CONCAT(slug) AS slugs
            FROM posts_categories
           GROUP BY post_id
       ) AS b ON a.post_id = b.post_id
  LEFT JOIN (
          SELECT post_id, GROUP_CONCAT(slug) AS slugs
            FROM posts_themes
           GROUP BY post_id
       ) AS c ON a.post_id = c.post_id
 ORDER BY a.post_id

诀窍是创建正确的摘要作为子查询,然后将它们连接到posts表。

注意:如果您只处理类别或仅处理主题,则可以避免子查询,只需LEFT JOIN posts_categories表,并对主查询执行GROUP BY。但是,如果您同时加入post_categoriesposts_themes表,则会在逗号分隔列表中获得组合爆炸和大量额外数据。