MySQL WHERE 子句中的多个 CASE WHEN 不起作用
MySQL Multiple CASE WHEN in WHERE clause not working
我正在尝试优化我的网站的搜索引擎。我的数据库包含短语。 @word
被定义为 varchar 并且包含与数据库中存在的短语相似的短语。
我想如果给定的搜索短语与数据库中的条目完全匹配,则将选择该条目,如果找不到任何内容,请使用 like '%phrase%'
进行搜索,如果使用此方法找不到任何内容,则 MATCH columnx against (phrase)
应使用方法。这是我尝试使用的代码:
select distinct columnx
from tabley
where
( CASE when columnx LIKE @word is not null
then columnx LIKE @word
when columnx like concat('%',@word,'%') is not null
then columnx like concat('%',@word,'%')
else MATCH (columnx) AGAINST (@word) END
);
为了确保独立 select 查询中的案例是否正常工作,我在 where 子句中单独使用了它们。我得到这些查询的结果:
select distinct columnx from view_materialisiert where MATCH (columnx) AGAINST (@word);
和
select distinct columnx from view_materialisiert where columnx like concat('%',@word,'%');
正如预期的那样没有结果:
select distinct columnx from view_materialisiert where columnx like @word;
问题是为什么我在使用 case 条件时没有得到任何结果?
如果您想要匹配三个条件中任何一个的值,您可以使用布尔逻辑:
select columnx
from tabley
where columnx = @word
or columnx like concat('%', @word, '%')
or match(columnx) against (@word)
或者您可以扩展 case
逻辑:
where case
when columnx = @word then 1
when columnx like concat('%', @word, '%') then 1
when match(columnx) against (@word) then 1
end
不过我不确定这是否真的符合您的期望。似乎您想反复检查条件,仅当前一个在整个 table 上不匹配时才尝试下一个。这种类型的逻辑通常用 union all
和 not exists
:
来实现
select columnx
from tabley
where columnx = @word
union all
select columnx
from tabley
where columnx like concat('%', @word, '%')
and not exists (select 1 from tabley where columnx = @word)
union all
select columnx
from tabley
where match(columnx) against (@word)
and not exists (select 1 from tabley where columnx = @word)
and not exists (select 1 from tabley where columnx like concat('%', @word, '%'))
数据库如何优化此类查询在很大程度上取决于您的数据和其他因素。在最好的情况下,一旦一个成员 returns 发生任何事情,以下成员将被“跳过”(因为 not exists
子查询对此非常明确),但不能保证。您需要评估实际数据集的性能。
只做
MATCH (columnx) AGAINST ("+word" IN BOOLEAN MODE)
非常快。该表达式消除了对精确匹配和其他一些情况的需要。
提到的 OR
方法效率很低。他们会检查每一行,通常是每次测试。
注意事项:
- 不能使用“短”字。
- 不能使用“停止”字样。
- 如果您不注意这些限制,您将一无所获。所以做一些预处理来决定什么时候
MATCH
会起作用。
我正在尝试优化我的网站的搜索引擎。我的数据库包含短语。 @word
被定义为 varchar 并且包含与数据库中存在的短语相似的短语。
我想如果给定的搜索短语与数据库中的条目完全匹配,则将选择该条目,如果找不到任何内容,请使用 like '%phrase%'
进行搜索,如果使用此方法找不到任何内容,则 MATCH columnx against (phrase)
应使用方法。这是我尝试使用的代码:
select distinct columnx
from tabley
where
( CASE when columnx LIKE @word is not null
then columnx LIKE @word
when columnx like concat('%',@word,'%') is not null
then columnx like concat('%',@word,'%')
else MATCH (columnx) AGAINST (@word) END
);
为了确保独立 select 查询中的案例是否正常工作,我在 where 子句中单独使用了它们。我得到这些查询的结果:
select distinct columnx from view_materialisiert where MATCH (columnx) AGAINST (@word);
和
select distinct columnx from view_materialisiert where columnx like concat('%',@word,'%');
正如预期的那样没有结果:
select distinct columnx from view_materialisiert where columnx like @word;
问题是为什么我在使用 case 条件时没有得到任何结果?
如果您想要匹配三个条件中任何一个的值,您可以使用布尔逻辑:
select columnx
from tabley
where columnx = @word
or columnx like concat('%', @word, '%')
or match(columnx) against (@word)
或者您可以扩展 case
逻辑:
where case
when columnx = @word then 1
when columnx like concat('%', @word, '%') then 1
when match(columnx) against (@word) then 1
end
不过我不确定这是否真的符合您的期望。似乎您想反复检查条件,仅当前一个在整个 table 上不匹配时才尝试下一个。这种类型的逻辑通常用 union all
和 not exists
:
select columnx
from tabley
where columnx = @word
union all
select columnx
from tabley
where columnx like concat('%', @word, '%')
and not exists (select 1 from tabley where columnx = @word)
union all
select columnx
from tabley
where match(columnx) against (@word)
and not exists (select 1 from tabley where columnx = @word)
and not exists (select 1 from tabley where columnx like concat('%', @word, '%'))
数据库如何优化此类查询在很大程度上取决于您的数据和其他因素。在最好的情况下,一旦一个成员 returns 发生任何事情,以下成员将被“跳过”(因为 not exists
子查询对此非常明确),但不能保证。您需要评估实际数据集的性能。
只做
MATCH (columnx) AGAINST ("+word" IN BOOLEAN MODE)
非常快。该表达式消除了对精确匹配和其他一些情况的需要。
提到的 OR
方法效率很低。他们会检查每一行,通常是每次测试。
注意事项:
- 不能使用“短”字。
- 不能使用“停止”字样。
- 如果您不注意这些限制,您将一无所获。所以做一些预处理来决定什么时候
MATCH
会起作用。