Reputation: 441
I am trying to optimize the search engine of my wensite. My data base contains phrases. @word
is defined as varchar and contains a similar phrase to the one which exist in the DB.
I want if the given search phrase matches exactly to the entry in DB the entry will be chosen, if nothing could be found, search with like '%phrase%'
and if nothing will be find with this method, then the MATCH columnx against (phrase)
method should be used. This is the code I tried with:
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
);
To make sure if the cases on a standalone select query works fine I used them separately in where clause. I get result for these queries:
select distinct columnx from view_materialisiert where MATCH (columnx) AGAINST (@word);
and
select distinct columnx from view_materialisiert where columnx like concat('%',@word,'%');
And as expected no result for:
select distinct columnx from view_materialisiert where columnx like @word;
The question is why i dont get any result when I use the case condition at all?
Upvotes: 0
Views: 80
Reputation: 142278
Do only
MATCH (columnx) AGAINST ("+word" IN BOOLEAN MODE)
It is very fast. That expression eliminates the need for the exact match and some of the other cases.
The OR
approaches mentioned are quite inefficient. They will check every row, usually with every test.
Caveats:
MATCH
will work.Upvotes: 0
Reputation: 222432
If you want values that match on any of the three condition, you can use boolean logic:
select columnx
from tabley
where columnx = @word
or columnx like concat('%', @word, '%')
or match(columnx) against (@word)
Or you can extend the case
logic:
where case
when columnx = @word then 1
when columnx like concat('%', @word, '%') then 1
when match(columnx) against (@word) then 1
end
However I am unsure that's really what you expect. It seems like you want to iteratively check the conditions, trying the next one only when the preceding had no match on the entire table. This type of logic would be typically implemented with union all
and 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, '%'))
How the database will optimize such query is highly dependent on your data and other factors. In the best case scenario, the following members will be "skipped" as soon as one member returns anything (because the not exists
subquery is quite explicit about that), but there is no guarantee. You would need to assess the performance on your actual dataset.
Upvotes: 1