mysql - 我应该如何合并这些选择并缩小结果集?

标签 mysql search

我有一个巨大的查询,可以从一系列关键字中过滤结果。

select distinct textures.id from textures
WHERE ((textures.id in (
        select tt.texture_id
        from tag_texture tt join tags t
        on t.id = tt.tag_id
        where t.name in ('tag1', 'tag2')
        group by tt.texture_id
        HAVING COUNT(DISTINCT t.id) = 2
        )
)  OR (textures.id in (
        select ct.texture_id
        from category_texture ct join categories c
        on c.id = ct.category_id
        where c.name in ('category1', 'category2')
        group by ct.texture_id
        HAVING COUNT(DISTINCT c.id) = 2
        )
)  OR (textures.id in (
        select tex.id
        from textures tex
        where tex.name LIKE 'texturename'
        group by tex.id
        HAVING COUNT(DISTINCT tex.id) = 1
        )
) ) AND textures.is_published = 1

问题是,如果我搜索texturename tag1,将找到所有texturename结果,即使它们与标签无关。但是,如果我搜索“tag1 tag2”,结果列表将被过滤掉(结果比仅搜索 tag1 少)。显然,将这​​些 OR 更改为 AND 可以进一步扩大结果范围。

合并这些结果的最佳方法是什么,以便每次过滤单词时都能缩小结果集的范围?

最佳答案

将所有 OR 更改为 AND 应该可以解决问题:

SELECT id, name 
FROM textures
WHERE ((textures.id in (
        select tt.texture_id
        from tag_texture tt join tags t
        on t.id = tt.tag_id
        where t.name in ('1k', 'test')
        group by tt.texture_id
        HAVING COUNT(DISTINCT t.id) = 2
        )
)  AND (textures.id in (
        select ct.texture_id
        from category_texture ct join categories c
        on c.id = ct.category_id
        where c.name in ('mine')
        group by ct.texture_id
        HAVING COUNT(DISTINCT c.id) = 1
        )
)  AND (textures.id in (
        select tex.id
        from textures tex
        where tex.name LIKE '%apple%'
        group by tex.id
        HAVING COUNT(DISTINCT tex.id) = 1
        )
) ) AND textures.is_published = 1

SqlFiddle

在此查询中无需使用DISTINCT。您没有与任何其他表连接,因此不会导致结果相乘。

如果您想在所有字段中搜索相同的关键字,并要求每个字段至少有一个匹配,请去掉 GROUP BYHAVING 条款。

select textures.id, textures.name from textures
WHERE ((textures.id in (
        select tt.texture_id
        from tag_texture tt join tags t
        on t.id = tt.tag_id
        where t.name in ('1k', 'test', 'apple', 'mine')
        )
)  AND (textures.id in (
        select ct.texture_id
        from category_texture ct join categories c
        on c.id = ct.category_id
        where c.name in ('1k' 'test', 'apple', 'mine')
        )
)  AND (textures.id in (
        select tex.id
        from textures tex
        where tex.name LIKE '%1k%' OR tex.name LIKE '%test%' OR tex.name LIKE '%apple%'
          OR tex.name LIKE '%mine%'
        )
) ) AND textures.is_published = 1

我将我的添加到关键字列表中,因为否则categories表中没有匹配项。

SqlFiddle

关于mysql - 我应该如何合并这些选择并缩小结果集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31439156/

相关文章:

c# - 用于索引文档和文本的良好搜索技术是什么

mysql - 从多个表中选择更新表

python - 由于缺少 mysql_config,在 OSX 上安装 MySQL-python 失败

php - 如何从连接表结果中同名的两个值中获取单个值?

java - 如何编写防止部分匹配的正则表达式

python - 我如何线性搜索和比较两个 .text 文件以查看它们之间缺少什么?

带复选框的 Android 可过滤回收 View

mysql - 避免 SELECT 查询中的冗余表达式

php - 在纯 PHP 中从 slug 博客标题创建 View

c++ - 需要改进我的代码的建议 : Search Algorithm