【问题标题】:How can I select all posts which have specific tags?如何选择所有具有特定标签的帖子?
【发布时间】:2017-06-08 20:22:22
【问题描述】:

这是我的表结构:

// posts
+----+-----------+---------------------+-------------+
| id |   title   |        body         |   keywords  |
+----+-----------+---------------------+-------------+
| 1  | title1    | Something here      | php,oop     |
| 2  | title2    | Something else      | html,css,js |
+----+-----------+---------------------+-------------+

// tags
+----+----------+
| id |   name   |
+----+----------+
| 1  | php      |
| 2  | oop      |
| 3  | html     |
| 4  | css      |
| 5  | js       |
+----+----------+

// pivot
+---------+--------+
| post_id | tag_id |
+---------+--------+
| 1       | 1      |
| 1       | 2      |
| 2       | 3      |
| 2       | 4      |
| 2       | 5      |
+---------+--------+

好吧,我有两个标签(phphtml),我需要选择所有带有它们标签的帖子。我该怎么做?

目前我使用REGEXP 并简单地选择我想要的:

SELECT * FROM posts WHERE keywords REGEXP 'php|html';

看到了吗?我什至不使用 1 join。这些天我的数据集长大了,我的查询需要一段时间才能执行。我想我必须使用像join 这样的关系功能。但是我不确定它会比我当前的查询更好。

无论如何,有人知道,我怎样才能更快地得到预期的结果?

【问题讨论】:

  • 您应该在适当的相关表格中规范化您的数据(关键字内容)
  • 在帖子表中应该有带有标签ID的列,然后您可以从帖子表中选择。
  • @scaisEdge 你到底是什么意思?如果您写一个答案并解释您建议的数据库设计,我会很高兴。
  • @MartinAJ 你可以使用like。 where(关键字如 '%php%' 或关键字如 '%html%')。

标签: mysql sql join


【解决方案1】:

正则表达式的处理速度可能很慢。使用LIKE 可能会提供更好的响应时间:

SELECT * 
FROM   posts 
WHERE  (keywords LIKE '%php%' OR keywords LIKE '%html%')

基于规范化表的查询将是:

SELECT     posts.id, posts.title, posts.body, posts.keywords 
FROM       posts
INNER JOIN pivot ON pivot.post_id = posts.id
INNER JOIN tags ON tags.id = pivot.tag_id
WHERE      tags.name IN ('html', 'php')
GROUP BY   posts.id

为了获得最佳速度,您必须确保将 id 字段声明为主键,并且您在以下方面有索引:

tags(name)
pivot(tag_id)

不过,如果所有帖子的很大一部分都满足条件,这不会比您当前的解决方案更快:它很可能会更慢。但是,例如,如果少于 1% 的帖子满足条件,那么这可能会执行得更好,因为原则上执行计划不需要包括对整个帖子表的扫描。

【讨论】:

  • 你能告诉我GROUP BY 在你的第二个查询中做了什么吗?对我来说似乎没用。如果我删除它会发生什么?注意到我在现实中使用了= 而不是IN
  • group by 用于避免在结果集中重复相同的帖子。当帖子在数据透视表中有两个匹配条目(一个用于“html”,一个用于“php”)时,可能会发生这种情况。当你不使用in,只与=比较为一个值时,当然不需要分组。但是您在问题中的示例提到了两个标签。
【解决方案2】:

您已经有了一个具有多对多关系的规范化设计。帖子表中不需要关键字列,因为枢轴已经建立了相同的。

您只需要正确地进行连接。试试这个:

SELECT posts.id
  FROM posts
LEFT OUTER JOIN pivot
  ON posts.id = pivot.post_id
LEFT OUTER JOIN tags
  ON pivot.tag_id = tags.id
WHERE tags.name = "php" or tags.name = "html"
GROUP BY posts.id;

这将为您提供带有标签的帖子的所有 ID。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多