在哪里使用多个关键字

时间:2015-07-14 22:23:02

标签: mysql sql

我有一个相当复杂的查询,它在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`

在此示例中,图稿是一个类别,master和super是标签。问题是如果我重复任何表,都没有找到结果:

  1. 艺术品(类别)+主人(标签)作品
  2. 艺术作品
  3. 艺术品+大师+超级不起作用 - 它应该打印所有具有艺术品作为类别和2个标签(主要和超级)的纹理,但它不会。
  4. 提前致谢。

    为清晰起见编辑:

    我的目标是能够在这些表中搜索数据,这样我就可以组合同一个表的多个实例。例如,如果我搜索“艺术品超级大师”,它应该返回我的所有纹理与“艺术品”类别(因为它是唯一找到该单词的地方)和标签“超级”和“主人”(两者都是)。

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

2 个答案:

答案 0 :(得分:1)

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

也许这对你有用:

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,我已经放入了原始示例中的值。

这整个查询非常难看,但它应该有效。 如果您需要执行此类搜索,则需要重新考虑数据结构。

答案 1 :(得分: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