mysql - 如何使用 JOIN 在 MySQL 上进行搜索?

标签 mysql

谁能告诉我在数据库中进行这种搜索的方法?

我得到了这些表:

posts (id, tags_cache)
tags (id, name)
posts_tags (post_id, tag_id)

用户输入搜索查询(比如“water blue”),我想显示同时具有这两个标签的帖子。 我能想到的唯一搜索方法是使用 FIND_IN_SET,这样:

SELECT p.*, GROUP_CONCAT(t.name) AS tags_search
FROM posts p
LEFT JOIN posts_tags pt ON p.id = pt.post_id
LEFT JOIN tags t ON pt.tag_id = t.id
GROUP BY p.id
HAVING FIND_IN_SET('water', tags_search) > 0
AND FIND_IN_SET('blue', tags_search) > 0

posts.tags_cache text 列存储它所属标签的名称和 id(这样:water:15 blue:20).

为了避免通过使用此列进行搜索来进行 JOIN,我尝试了 LIKEINSTR 但这些会给出不准确的结果,因为您可以搜索“ter ”,例如,您将获得标记为“water”和“termal”的帖子。我还尝试了 REGEXP,它给出了准确的结果,但这是一个缓慢的过程。

我不能使用 MATCH,因为表使用 InnoDB。

那么...是否有其他方法可以做到这一点?

[编辑]

我忘了说用户可以搜索很多标签(不仅仅是 2 个),甚至可以排除标签:搜索标签为“water”但不是“blue”的帖子。使用 FIND_IN_SET 这对我有用:

HAVING FIND_IN_SET('water', tags_search) > 0
AND NOT FIND_IN_SET('blue', tags_search) > 0

[编辑2]

我按照 ypercube 的建议做了一些性能测试(即只检查查询花费了多长时间,缓存),结果如下:

muists | Bill K | ypercu | includes:excludes
--------------------------
0.0137 | 0.0009 | 0.0029 | 2:0
0.0096 | 0.0081 | 0.0033 | 2:1
0.0111 | 0.0174 | 0.0033 | 2:2
0.0281 | 0.0081 | 0.0025 | 5:1
0.0014 | 0.0013 | 0.0015 | 0:2

我不知道这个信息是否是有效资源...但它表明 ypercube 的每个标签 JOIN 方法是最快的。

最佳答案

我不明白您为什么不想使用 JOIN,也不明白您为什么要尝试使用 LEFT JOIN。您正在寻找存在的东西(而不是可能存在的东西),所以去掉 LEFT JOIN 并只加入 JOIN。并删除 tags_cache 列,你只是在自找麻烦。

你要找的就是这样的东西:

select p.id
from posts p
join posts_tags pt on p.id = pt.post_id
join tags t on pt.tag_id = t.id
where t.name in ('water', 'blue')
group by p.id
having count(t.id) = 2

HAVING 子句中的 2 是您要查找的标签数。

如果你想排除某些标签,你可以像这样将它添加到 WHERE 子句中:

select p.id
from posts p
join posts_tags pt on p.id = pt.post_id
join tags t on pt.tag_id = t.id
where t.name in ('water', 'blue')
  and p.id not in (
    select pt.post_id
    from posts_tags pt
    join tags t on pt.tag_id = t.id
    where t.name in ('pancakes', 'eggs') -- Exclude these
)
group by p.id
having count(t.id) = 2

关于mysql - 如何使用 JOIN 在 MySQL 上进行搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8106547/

相关文章:

mysql - Haproxy根据请求中的域名对Mysql连接进行负载均衡

mysql - 如何使用mysql中不存在的地方?

java - 迁移数据库时如何判断column是Blob

mysql - MySQL中大数据的慢计数查询

MySQL GROUP_CONCAT 排除组值

mysql - req.body 在 postman 上运行时说未定义

MySQL REGEXP NOT 组运算符

mysql - 检查数据库中以出生日期格式存储在列中的值

php - 根据Mysql查询结果显示

php - 用PHP读取带有控制字符的TXT文件