I am creating a "simple" search query. I'd like to select a column that should have the value 1 if a specified column LIKE('test'), it's kind of hard to explain.
What i want to do is like this
SELECT *,(CASE mycol LIKE('%test%') as match THEN 1 END) FROM mytable
So if mycol matches the condition, then match=1, if else 0. How would i do that? Sorry if hard to understand.
You are nearly there, but you have made four errors and used one bad practice:
Add ELSE 0 in your CASE expression.
CASE expressions need one or more WHEN expressions.
Put the alias in the correct place - after the end of the expression.
Don't use the reserved word match as an alias.
Also, don't use SELECT *.
Try this:
SELECT
col1,
col2,
...,
coln,
CASE WHEN mycol LIKE '%test%' THEN 1 ELSE 0 END AS zipmatches
FROM mytable
However there's no need for the CASE expression in MySQL because TRUE and 1 are equivalent:
SELECT
col1,
col2,
...,
coln,
mycol LIKE '%test%' AS zipmatches
FROM mytable
Here is another expression
SELECT *, IF(mycol LIKE('%test%'),1,0) is_a_match FROM mytable;
Related
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?
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.
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:
"Short" words cannot be used.
"Stop" words cannot be used.
If you aren't careful about those limitations, you will get nothing or everything. So do some preprocessing to decide when MATCH will work.
For example if I want to search below.
> lav'ro (I can't search it by "lav'r" because of ' in the string)
> am[op]st (I can't search it by "am[o" because of [ in the string)
My question is how can I use select query so I will help me to bring output?
Below are my SELECT query.
SELECT * FROM TableName
WHERE (Col1 LIKE '%$value%' OR Col2 LIKE '%$value%')
ORDER BY
CASE WHEN (Col1 LIKE '$value' AND Col2 LIKE '$value') THEN 1
WHEN Col1 LIKE '$value' THEN 2
WHEN Col2 LIKE '$value' THEN 3
WHEN Col1 LIKE '$value%' THEN 4
WHEN Col2 LIKE '$value%' THEN 5
WHEN Col1 LIKE '%$value' THEN 6
WHEN Col2 LIKE '%$value' THEN 7
WHEN Col1 LIKE '%$value%' THEN 8
WHEN Col2 LIKE '%$value%' THEN 9
ELSE 10
END asc,
length(Col1 or Col2) limit 15
Here "$value" dynamic word for search.
It's working well In normal search, problem with symbolic search.
You have to include \ before the single quote to make it work
SELECT * FROM `table` WHERE `column` LIKE 'lav\'ro'
For the 2nd issue try % to append before or after or both
SELECT * FROM `table` WHERE `column` LIKE '%am[o%'
You don't have to use like. You can just use instr() or =:
where instr(col1, ?) > 0
Use like and regular expressions when you need them for their pattern matching capabilities.
And -- for the record -- there is no problem searching for single quotes in a string. The only problem is expressing the string. To do this, double up on the single quote:
where col1 like concat(?, '%')
works when you pass a parameter with a single quote. This also works:
where col1 like 'lav''r%'
My database has 2 columns that contain text. When it has say 3 records as follows:
rec# col1 col2
1 my name is fred is
2 john mike
3 today not sat not it sat
I would appreciate help constructing a regular expression that will return record numbers:
1 -> because "is" matches
3 -> because "'not" and "sat" match (i.e. at least one match exists)
I think you can do this as:
select t.*
from table t
where col1 rlike replace(col2, ' ', '|');
This turns col2 into a regular expression. So, note that this answer will be very sensitive to the contents of col2. If it contains regular expression special characters, then this probably will not work.
What do you mean by "matches"?
This SELECT will find the rows where col1 contains at least one of the words is or not or sat:
SELECT rec_num
FROM tbl
WHERE col1 REGEXP '[[:<:]](is|not|sat)[[:>:]]';
This says that at least one of those words exists in both col1 and col2:
SELECT rec_num
FROM tbl
WHERE col1 REGEXP '[[:<:]](is|not|sat)[[:>:]]'
AND col2 REGEXP '[[:<:]](is|not|sat)[[:>:]]';
Change AND to OR to ask if one of the words exists in either (or both) column.
If you need the same word (is/not/sat) to match both col1 and col2, that is more complex:
SELECT rec_num
FROM tbl
WHERE ( col1 REGEXP '[[:<:]]is[[:>:]]'
AND col2 REGEXP '[[:<:]]is[[:>:]]' )
OR ( col1 REGEXP '[[:<:]]not[[:>:]]'
AND col2 REGEXP '[[:<:]]not[[:>:]]' )
OR ( col1 REGEXP '[[:<:]]sat[[:>:]]'
AND col2 REGEXP '[[:<:]]sat[[:>:]]' );
If you mean something else, practice asking precise questions.
Addenda
It is not practical in SQL to discover which words (if any) are in common between two text fields. Such a task would be better done in an application programming language (PHP, Java, Perl, ...).
I am wondering how could i say not an empty string in MYSQL with Regular Expression.
My thought :
SELECT * FROM `table` WHERE `column` <> '^$'
I am totally newby as far as Regular Expressions are concerned. And not a pro at all in MySQL.
Use LENGTH():
SELECT * FROM table
WHERE LENGTH(column) > 0
This (correctly) returns rows that are one or more spaces, and doesn't return nulls.
Note that
WHERE column <> ''
behaves differently. <> ignores trailing spaces, so a column that contains (only) spaces will be considered the same as '', so such rows will be excluded from the selection. If that is what you want, then you can either do:
SELECT * FROM table
WHERE column <> ''
OR
SELECT * FROM table
WHERE LENGTH(TRIM(column)) > 0
Either way, a column containing NULL will evaluate the WHERE expression to NULL, which will exclude the column from the selection. (It is not necessary to also do "AND column IS NOT NULL")
The solution depends on whether you want columns containing only blanks to be considered "empty".
To consider blanks to be empty, and exclude them from the selection, do:
SELECT * FROM `table` WHERE `column` <> '' AND `column` IS NOT NULL
NOTE: TRIM(column) is not needed here, because <> ignores trailing blanks. However, if you feel that TRIM(column) makes the intent clearer, there is no harm in including it:
SELECT * FROM `table` WHERE TRIM(`column`) <> '' AND `column` IS NOT NULL
This has exactly the same result as the first version.
To consider blanks to not be empty, and include them in the selection, use Bohemian's accepted answer.
If you really want use REGEX you should check this
SELECT * FROM `table` WHERE `column` REGEX '^$' AND `column` IS NOT NULL
But I don't recommend using REGEX for checking if string is empty.
UPDATE:
In all of the above answers, "AND column IS NOT NULL" could be omitted. A column containing NULL will evaluate the WHERE expression to NULL, which will exclude the column from the selection.
So the same result can be obtained with the simpler:
SELECT * FROM `table` WHERE `column` <> ''
This is not a comparison to regular expression:
SELECT * FROM `table` WHERE `column` <> '^$'
This is:
SELECT * FROM `table` WHERE `column` REGEX '^$'
or
SELECT * FROM `table` WHERE `column` RLIKE '^$'
One of the first things in learning about regular expressions is when to use them and when not to. This is a case not to. You should just do:
SELECT * FROM `table` WHERE `column` <> ''
By the way, all of these comparisons automatically fail when the value is NULL. If you want to allow NULL values, you would have to do that explicitly.
fieldname REGEXP '^$|^[[:blank:]]+$|^[[:space:]]+$' OR fieldname IS NULL
I am trying to search multiple columns in my Db using a regex. It works but using many and/or statments. I was wondering if it was possible to use something like this;
SELECT * FROM table REGEXP 'regex' IN (col1, col2, col3,.....)
This doesn't work, it was a guess at the syntax because I can't find anything similar by searching online. Is this a stupid idea or am I missing something very simple?
If you want to regexp search a value in multiple columns then you can do:
SELECT * FROM table where CONCAT(col1, col2, col3) REGEXP 'search-pattern';
The syntax for MySQL REGEX comparison is
expr REGEXP pattern_string
You cannot use it with IN. You would have to do:
SELECT * FROM `table` WHERE
col1 REGEXP 'regex'
OR col2 REGEXP 'regex'
OR col3 REGEXP 'regex'
You could also use RLIKE -- they are synonyms.