【问题标题】:Getting tags for content from second table in one sql在一个 sql 中从第二个表中获取内容的标签
【发布时间】:2011-12-05 22:54:16
【问题描述】:

我有两张表,一张用于帖子,一张用于与帖子相关的标签,其中posts.tags 保存与帖子相关的标签的ID。

帖子:

id | title  | tags
-----------------
 1 | Foobar | 1 3 7
 2 | Barfoo | 2 3 7

标签:

id | tag
--------
 1 | Tag1
 2 | Tag2
... and so forth

在查询帖子时,我希望得到一个帖子,其所有标签都是以空格分隔的字符串,而不是标签 ID 字符串。

我试过这样的查询:

SELECT *, 
(
  SELECT GROUP_CONCAT(tags.tag)
  FROM tags 
  WHERE tags.id LIKE 1 OR tags.id LIKE 3
) AS tag_str
FROM posts

这基本上输出了我正在寻找的东西;我想不通的是子条款中正确的 WHERE 条件,用我自己的话来说,它会检查“标签 WHERE tag.id 是否匹配posts.tags 中的任何空格分隔的数字字符串”——如果有任何这样的查询有可能吗?

任何帮助表示赞赏, k.

【问题讨论】:

  • 当然,正如 Joe 在下面提到的,您应该使用一个多对多表,将主键 post.id 与主键 tags.id 链接起来。这将避免必须从数据库中解析字符串,减少错误并做出更好的整体设计。
  • 如果他不能改变数据库结构,我建议他使用CONCAT(' ', tags.id, ' ') LIKE '% 3 %'。事实上,如果他只使用'%3%',标签#13 或#34 等也会被拾取。

标签: mysql tags group-concat


【解决方案1】:

您的基本数据库设计存在缺陷,现在您正遭受该缺陷的后果。如果您有任何可能解决此问题,您应该这样做。标签不应该作为空格分隔的字符串存储在 Posts 表的单个列中。相反,您应该有一个联结表Posts_Tags_xref,它可以解决多对多关系。此表将包含两个外键,Posts.idTags.id

对于上面的示例数据,您将拥有:

Posts_Tags_xref
==================
post_id     tag_id
-------     ------
      1          1
      1          3
      1          7
      2          2
      2          3
      2          7

您要查询的查询变为:

SELECT p.post_id, p.title, GROUP_CONCAT(t.tag)
    FROM Posts p
        LEFT JOIN Posts_Tags_xref ptx
            INNER JOIN Tags t
                ON ptx.tag_id = t.tag_id
            ON p.post_id = ptx.post_id
    GROUP BY p.post_id, p.title;

【讨论】:

  • 感谢您帮助我将“奇怪的直觉这行不通”重新定义为“多对多问题”。然后将其拆分为连接表。
猜你喜欢
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
  • 1970-01-01
  • 2014-10-06
  • 2015-01-18
相关资源
最近更新 更多