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 allnot 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 会起作用。