sql - 查询以根据标签查找主题

标签 sql ruby-on-rails mysql

我想要在我的应用程序中搜索如下数据的功能

topic_id   tag
1          cricket
1          football
2          football
2          basketball
3          cricket
3          basketball
4          chess
4          basketball

现在,当我搜索术语 cricket AND football 时,o/p 应该是

 topic_id
    1

当我搜索术语时 cricket OR football o/p 应该是

 topic_id
    1
    2
    3

我尝试像下面这样的东西

对于和

  select topic_id from table_name where tag like "%cricket%" and topic_id in (select topic_id from table_name where tag like "%football%")

为了或

 select topic_id from table_name where tag like "%cricket%" OR tag like "%football%"

我的问题是,当用户搜索 cricket AND football AND basketball AND chess 时,我的查询变得非常可悲

有什么简单的解决办法吗?我也试过 GROUP_CONCAT 但没有成功

最佳答案

 SELECT TopicId
 FROM Table
 WHERE Tag IN ('cricket', 'football', 'basketball', 'chess')
 GROUP By TopicId
 HAVING Count(*) = 4

  4 is magic number - its a length of your AND list.

 FOR cricket AND football

 it will be 2:

 SELECT TopicId
 FROM Table
 WHERE Tag IN ('cricket', 'football')
 GROUP By TopicId
 HAVING Count(*) = 2

 if you want use 'like' statement:

 SELECT TopicId
 FROM Table
 WHERE Tag IN (SELECT distinct Tag from Table Where Tag like '...'
                OR Tag like '...'
                OR Tag like '...'
                OR Tag like '...'
              )
 GROUP By TopicId
 HAVING Count(*) = (SELECT COUNT(distinct Tag) from Table 
                    Where Tag like '...'
                       OR Tag like '...' 
                       OR Tag like '...'
                       OR Tag like '...'
                   )

更新:

使用支持所有集合操作的 RDBMS 可以轻松解决此任务:UNIONINTERSECTEXCEPT(或MINUS)

然后任何条件如:

  1. (Tag1 AND Tag2)或 Tag3 NOT Tag4
  2. 标记 1 或标记 2
  3. 标签 1 和标签 2 和标签 3
  4. (标记 1 和标记 2)或(标记 3 和标记 4)

可以很容易地转化为:

1. (Select * ... Where Tag = Tag1
    INTERSECT
    Select * ... Where Tag = Tag2
   )
   UNION
   (Select * ... Where Tag = Tag3)
   EXCEPT
   (Select * ... Where Tag = Tag4)

2. Select * ... Where Tag = Tag1
   UNION
   Select * ... Where Tag = Tag2

3. Select * ... Where Tag = Tag1
   INTERSECT
   Select * ... Where Tag = Tag2
   INTERSECT
   Select * ... Where Tag = Tag3

 4.(Select * ... Where Tag = Tag1
    INTERSECT
    Select * ... Where Tag = Tag2
   )
   UNION
   (Select * ... Where Tag = Tag1
    INTERSECT
    Select * ... Where Tag = Tag2
   )

真正的问题是MYSQL不支持INTERSECT,应该模拟如上图。第二个问题是尊重括号和运算符优先级。

在表达式中不使用括号的可能解决方案:

  1. 收集所有由 AND 条件连接的标签,并构建查询作为答案中的第一个示例。

  2. 将所有加入 OR 条件(可以使用 IN 或 UNION)的标签相加,并使用 UNION 合并结果。

另一种方法只有当你的标签数量少于 64 时才有可能。然后每个标签都有自己的位(你需要将 bigint 字段'tags'添加到主题表中,其中将以二进制格式表示标签)并使用 mysql 位操作创建查询。

最大的缺点是该解决方案仅限于 64 个标签。

关于sql - 查询以根据标签查找主题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3369195/

相关文章:

mysql - 如何合并两个具有不同列号的表? mysql

sql - NHibernate Profiler 无法连接到 session 和记录

ruby-on-rails - 将静态 JSON 文件解析为 Rails 对象

php - 如何从其他国家语言的数据库中获取日期?

mysql - 有人可以帮我用 R 编程解决这个问题吗?

php - 或者 INNER JOIN 中的条件

ruby-on-rails - 如何创建自定义路由助手以供在 routes.rb 中使用

ruby-on-rails - 如果记录存在,Rails 如何改进?

mysql - 根据条件从2个不同的表中选择数据; mysql

mysql - MySQL 中生成的列中的日期时间错误