【问题标题】:Most efficient way to concat rows连接行的最有效方法
【发布时间】:2014-12-06 15:03:11
【问题描述】:

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

帖子 - post_id - 姓名 - 描述

posts_categories - post_id - 蛞蝓

posts_themes - post_id - 蛞蝓

基本上我想查询这样的帖子列表:

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

我想组合相关的类别和主题表并将它们连接到一个列中。所以我的输出是:

1 |测试 |描述 |音乐、艺术、历史| 高分辨率照片| CLIPARTO重要的,相关的,新的

我已尝试将此作为子查询,但遇到了返回多行的常见问题。我也尝试过 LEFT JOIN'ing 结果,但似乎无法返回正确的结果。由于害怕在不知不觉中干扰我的结果,我希望有人可以帮助制定最有效和最正确的查询。

谢谢。

【问题讨论】:

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


    【解决方案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.

    【讨论】:

    • 我更喜欢你的解决方案而不是 Ollie Jone 的解决方案,但是我不知道为什么需要按名称和描述进行分组。我的数据集中也有重复的结果。我如何确保它们是独一无二的?我相信在 GROUP_CONCAT 之前抛出 DISTINCT() 会起作用。
    • @ddibiase 在 MySQL 中,如果 id 足够唯一,您可以仅按 id 分组,但是其他 RDBMS (postgresql/sql server/oracle/...) 甚至某些模式 MySQL 可以设置为更严格,并要求您按所有单个值分组。我不确定你得到什么样的重复,你能举个例子吗?
    【解决方案2】:

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

    考虑这个子查询:

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

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

    然后,您只需加入这些子查询,得到这个。

    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
    

    诀窍是创建正确的摘要作为子查询,然后将它们加入到帖子表中。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      相关资源
      最近更新 更多