【问题标题】:WHERE LIKE with multiple keywordsWHERE LIKE 有多个关键字
【发布时间】:2015-07-14 22:23:02
【问题描述】:

我有一个相当复杂的查询,它在 4 个表中搜索一个或多个关键字:

select distinct textures.id from textures
left join `category_texture` on `category_texture`.`texture_id` = `textures`.`id`
left join `categories` on `categories`.`id` = `category_texture`.`category_id`
left join `tag_texture` on `tag_texture`.`texture_id` = `textures`.`id`
left join `tags` on `tags`.`id` = `tag_texture`.`tag_id`
left join `size_texture` on `size_texture`.`texture_id` = `textures`.`id`
left join `sizes` on `sizes`.`id` = `size_texture`.`size_id` 
WHERE ( (textures.name LIKE '%artwork%' 
OR categories.name LIKE '%artwork%' 
OR tags.name LIKE '%artwork%'   
OR sizes.name LIKE '%artwork%')  AND  (textures.name LIKE '%super%' 
OR categories.name LIKE '%super%'   
OR tags.name LIKE '%super%' 
OR sizes.name LIKE '%super%')  AND  (textures.name LIKE '%master%' 
OR categories.name LIKE '%master%'  
OR tags.name LIKE '%master%'    
OR sizes.name LIKE '%master%') ) AND `textures`.`is_published` = 1  group by `tags`.`name`, `categories`.`name`, `sizes`.`name`, `textures`.`id`

在这个例子中,artifacts 是一个类别,master 和 super 是标签。问题是,如果我重复任何表格,都找不到结果:

  1. 艺术品(类别)+大师(标签)作品
  2. 艺术作品
  3. artwork + master + super 不起作用 - 它应该打印所有具有艺术品作为类别和 2 个标签(master 和 super)的纹理,但它没有。

提前致谢。

为清楚起见进行编辑:

我的目标是能够在这些表中搜索数据,从而可以组合同一个表的多个实例。例如,如果我搜索“artwork super master”,它应该返回我所有的纹理,类别为“artwork”(因为它是唯一找到这个词的地方)和标签“super”和“master”(两者都是)。

目前使用此查询,我可以在任何这些表中进行搜索,但前提是我的搜索在同一个表中没有找到 2 个以上的内容。因此,搜索类别 + 纹理名称 + 标记 + 大小是可行的,但搜索发现为 2 个标记的内容会失败。

【问题讨论】:

  • 查看正在查询的数据示例将真正帮助这里的人们。我认为这是最严格的查询 3,因为它正在过滤艺术品、超级和大师。 (未显示含义 1 和 2。)另外,“如果我重复任何表格”是什么意思?
  • 用更好的解释编辑了我的帖子。
  • 这似乎是 full text search 的创建对象。 dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
  • 不幸的是,我被要求“按原样”解决这个问题,而不是进行全文搜索:(
  • 显示的查询只会返回 3 个标签中的每一个都存在于 4 个表中的至少 1 个表中的行。它正在做你告诉它的事情。您似乎需要使用模式匹配搜索每个表(查询)的 single 实例,而不是您一直提到的“多个表”。你打算怎么搜索?搜索模式将如何输入到您的数据库中?

标签: mysql sql


【解决方案1】:

我重新考虑了一下,也许这种方法更好:

SELECT T1.id
FROM 
(  
select textures.id 
from textures
WHERE textures.name LIKE '%texture1%' 
UNION 
select textures.id 
from textures
join category_texture on category_texture.texture_id = textures.id
join categories on categories.id = category_texture.category_id
WHERE categories.name LIKE '%texture1%'
UNION
select textures.id 
from textures
join tag_texture on tag_texture.texture_id = textures.id
join tags on tags.id = tag_texture.tag_id
WHERE tags.name LIKE '%texture1%'
UNION 
select textures.id 
from textures
join size_texture on size_texture.texture_id = textures.id
join sizes on sizes.id = size_texture.size_id 
WHERE sizes.name LIKE '%texture1%'
) AS T1
JOIN 
(  
select textures.id 
from textures
WHERE textures.name LIKE '%category2%' 
UNION 
select textures.id 
from textures
join category_texture on category_texture.texture_id = textures.id
join categories on categories.id = category_texture.category_id
WHERE categories.name LIKE '%category2%'
UNION
select textures.id 
from textures
join tag_texture on tag_texture.texture_id = textures.id
join tags on tags.id = tag_texture.tag_id
WHERE tags.name LIKE '%category2%'
UNION 
select textures.id 
from textures
join size_texture on size_texture.texture_id = textures.id
join sizes on sizes.id = size_texture.size_id 
WHERE sizes.name LIKE '%category2%'
) AS T2
ON T1.id = T2.id
JOIN
(  
select textures.id 
from textures
WHERE textures.name LIKE '%tag3%' 
UNION 
select textures.id 
from textures
join category_texture on category_texture.texture_id = textures.id
join categories on categories.id = category_texture.category_id
WHERE categories.name LIKE '%tag3%'
UNION
select textures.id 
from textures
join tag_texture on tag_texture.texture_id = textures.id
join tags on tags.id = tag_texture.tag_id
WHERE tags.name LIKE '%tag3%'
UNION 
select textures.id 
from textures
join size_texture on size_texture.texture_id = textures.id
join sizes on sizes.id = size_texture.size_id 
WHERE sizes.name LIKE '%tag3%'
) AS T3
ON T1.id = T3.id

只需添加更多/更少JOIN...ON T1.id = Tn.id 部分以匹配您的参数。

这是一个显示它执行的小提琴:http://sqlfiddle.com/#!9/9abe6/1

【讨论】:

  • 注意:为了简单起见,我省略了 AND textures.is_published = 1group by whatever 子句。我认为每次选择都需要AND textures.is_published = 1。如果需要,请自行添加group
  • 我将对此进行一些测试并让您知道。基本上我需要通过这些测试:1)搜索“category2”将检索该类别的所有纹理; 2) 搜索“category2 tag3”将检索与这些特定信息匹配的纹理(在这种情况下,只有 category2 作为 category 和 tag3 作为 tag 的纹理应该显示); 3) 搜索“tag1 tag2 tag3”应该只检索在这种情况下具有这 3 个或更多类别的纹理。
  • 我做了一些修改,但您编辑的答案完全符合我的想法。非常感谢!
【解决方案2】:

您的查询尝试执行的操作存在两个问题。首先,参数的数量可能会有所不同,这需要为每个变体使用不同的查询语法(或者一些丑陋的黑客来解决它)。其次,对于每个表,当您想要返回所有行时,您只想返回与参数之一匹配的行除非没有匹配项

也许这对你有用:

select distinct textures.id 
from textures
join category_texture on category_texture.texture_id = textures.id
join categories on categories.id = category_texture.category_id
join tag_texture on tag_texture.texture_id = textures.id
join tags on tags.id = tag_texture.tag_id
left join size_texture on size_texture.texture_id = textures.id
join sizes on sizes.id = size_texture.size_id 
WHERE ((textures.name LIKE '%artwork%' OR textures.name LIKE '%super%' OR textures.name LIKE '%master%')  
  OR   (0 = select count(*) from textures where (textures.name LIKE '%artwork%' OR textures.name LIKE '%super%' OR textures.name LIKE '%master%') ) )
AND   ((categories.name LIKE '%artwork%' OR categories.name LIKE '%super%' OR categories.name LIKE '%master%') 
  OR   (0 = select count(*) from categories where (categories.name LIKE '%artwork%' OR categories.name LIKE '%super%' OR categories.name LIKE '%master%') ) )
AND   ((tags.name LIKE '%artwork%' OR tags.name LIKE '%super%' OR tags.name LIKE '%master%') 
  OR   (0 = select count(*) from tags where (tags.name LIKE '%artwork%' OR tags.name LIKE '%super%' OR tags.name LIKE '%master%') ) )
AND   ((sizes.name LIKE '%artwork%' OR sizes.name LIKE '%super%' OR sizes.name LIKE '%master%') 
  OR   (0 = select count(*) from name where (sizes.name LIKE '%artwork%' OR sizes.name LIKE '%super%' OR sizes.name LIKE '%master%') ) )
AND textures.is_published = 1   
group by textures.id, tags.name, categories.name, sizes.name, textures.name

编辑 由于您的代码动态生成 SQL,因此我已输入原始示例中的值。

整个查询非常丑陋,但它应该可以工作。 如果您需要进行这样的搜索,则需要重新考虑您的数据结构。

【讨论】:

  • 我认为你没有完全理解这个问题。这个查询是通过 PHP 动态构建的,所以参数的数量并不重要。然后,对于每个表,我想尝试匹配任何参数即使多个参数匹配同一个表。因此,如果在我的 5 个参数中,类别有两个匹配项,标签和纹理名称有 2 个匹配项,我想要 恰好 这两个类别、2 个标签和纹理名称的结果。
  • 谢谢,我修改了答案以更清楚地说明我的意思。您可以根据需要根据参数数量生成更多/更少的代码。我的(未经测试的)代码唯一已知的问题是,如果没有匹配项,它将返回所有内容。
猜你喜欢
  • 2011-11-06
  • 2014-08-30
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多