I have table column that contain strings seperated by , like so
Algebraic topology,Riemannian geometries
Classical differential geometry,Noncommutative geometry,Integral transforms
Dark Matter
Spectral methods,Dark Energy,Noncommutative geometry
Energy,Functional analytical methods
I am trying to search for the MySQL row that has a string between comma, for example if I was search for Noncommutative geometry, I want to select these two rows
Classical differential geometry,Noncommutative geometry,Integral transforms
Spectral methods,Dark Energy,Noncommutative geometry
This is what I tried
SELECT * FROM `mytable` WHERE ``col` LIKE '%Noncommutative geometry%'
which works fine, but there problem is that if I was searching for Energy I want to select the row
Energy,Functional analytical methods
but my code gives the two rows
Energy,Functional analytical methods
Spectral methods,Dark Energy,Noncommutative geometry
which is not what I am looking for. Is there a way to fix this so that it only finds the rows that have the string between commas?
Give these a try, using the REGEXP operator:
SELECT * FROM `mytable`
WHERE `col` REGEXP '(^|.*,)Noncommutative geometry(,.*|$)'
SELECT * FROM `mytable`
WHERE `col` REGEXP '(^|.*,)Energy(,.*|$)'
The expression being used ('(^|.*,)$searchTerm(,.*|$)') requires the search term to be either preceded by a comma or the beginning of the string, and followed by either a comma or the end of the string.
you can do like this
SELECT * FROM `mytable` WHERE `col` LIKE '%,$yourString,%'
or `col` LIKE '$yourString,%'
or `col` LIKE '%,$yourString'
Related
I need to search value starting with given string in comma separated values.
Example,
I have '1_2_3_4_5_6, 1_2_3_4_5_8, 1_2_3_6_5_8' in my column. I can search for rows with exact value using
select * from table where find_in_set('1_2_3_4_5_6',column)
But how to search, if starting part of the string is given? something like this:
select * from table where find_in_set('1_2_3%',column) ?
If I understand you correctly (I'm still not sure I do), you could just use:
SELECT * FROM table WHERE column LIKE '%1_2_3%';
This would give you columns where the value is like:
1_2_3_4_5_5
1_4_5_, 1_2_3_4_5_, 6_7
and so on.
But you should really normalize your tables. This is important for good queries and performance wise also important.
According to #Xatenev suggestions, if you really like only the values and the row of each matching row, this won't work so well and will be a lot of overhead. This are the steps that I would perform:
Split all CSV columns into multiple rows (this is a hack and a performance killer, I found some working solution but did not test it, see here): Pseudo Code: SELECT ID, SPLIT(',', column) AS entries FROM table (NOT WORKING)
Filter the new virtual table to select only rows that match the prefix (SELECT * FROM virtual_table WHERE find_in_set("1_2_3%, entries) ORDER BY ID)
Concatenate the matching entries back into a list for each ID. e.g. SELECT ID, GROUP_CONCAT(entries SEPARATOR ', ') FROM filtered_table GROUP BY ID
Do something
The unknown part is the beginning with the split in multiple rows. There are a lot of possible solutions all with their own drawbacks or advantages. Be aware that this will always (regardless of the selected method) will cost a lot of performance.
ADDITIONAL NODE:
It could be adventures in your situation, that you get each row matching your search string like in my first example and filter them in memory. This might be faster than doing this in MYSQL.
you can try with 'REGEXP'
If you want to match data with subtring, please try this
SELECT * FROM `table` WHERE `column` REGEXP '[, ]?1_2_3[^,]*,?' ;
Or
If you want to exact start match, please try this
SELECT * FROM `table` WHERE `column` REGEXP '[, ]?1_2_3[^,]*,?' AND `column` NOT REGEXP '[^, ]1_2_3[^,]*,?' ;
I was able to solve it with no-regex. Sonam's Answer is correct as well.
SELECT * from table WHERE CONCAT(',', columnname, ',') like '%,1_2_3%'
I've got a database table mytable with a column name in Varchar format, and column date with Datetime values. I'd like to count names with certain parameters grouped by date. Here is what I do:
SELECT
CAST(t.date AS DATE) AS 'date',
COUNT(*) AS total,
SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
AND (LOWER(t.name) LIKE '%[a-z]%')) AS 'n'
FROM
mytable t
GROUP BY
CAST(t.date AS DATE)
It seems that there's something wrong with range syntax here, if I just do LIKE 'a%' it does count properly all the fields starting with 'a'. However, the query above returns 0 for n, although should count all the fields containing at least one letter.
You write:
It seems that there's something wrong with range syntax here
Indeed so. MySQL's LIKE operator (and SQL generally) does not support range notation, merely simple wildcards.
Try MySQL's nonstandard RLIKE (a.k.a. REGEXP), for fuller-featured pattern matching.
I believe LIKE is just for searching for parts of a string, but it sounds like you want to implement a regular expression to search for a range.
In that case, use REGEXP instead. For example (simplified):
SELECT * FROM mytable WHERE name REGEXP "[a-z]"
Your current query is looking for a string of literally "[a-z]".
Updated:
SELECT
CAST(t.date AS DATE) AS 'date',
COUNT(*) AS total,
SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
AND (LOWER(t.name) REGEXP '%[a-z]%')) AS 'n'
FROM
mytable t
GROUP BY
CAST(t.date AS DATE)
I believe you want to use WHERE REGEXP '^[a-z]$' instead of LIKE.
You have regex in your LIKE statement, which doesn't work. You need to use RLIKE or REGEXP.
SELECT CAST(t.date AS DATE) AS date,
COUNT(*) AS total
FROM mytable AS t
WHERE t.name REGEXP '%[a-zA-Z]%'
GROUP BY CAST(t.date AS DATE)
HAVING SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
Also just FYI, MySQL is terrible with strings, so you really should trim before you insert into the database. That way you don't get all that crazy overhead everytime you want to select.
My problem is I have a table in which offers are stored and I want to display only those records who have 50% (the substring '50%' in them).
This is my table Schema:
An Example record would be:
FLAT 50% Off on Essel world entry tickets and more.
FLAT 50% Off on Rs
2495 & above. U.S polo - Upto 50% off
How would I go about composing an SQL query to select these? The column name of the field is called coupon_name
Like will do..
select * from table
where coupon_name like '%50[%]%'
This will give all records like below one having 250,this can be valid since percentage can't be greater than 100
sakfjfjk50%sfjbsadjkfbjksdf
sakfjfjk250%sfjbsadjkfbjksdf
I you need records containing '50%' you can use:
SELECT *
FROM YourTable
WHERE coupon_name LIKE '%50[%]%'
Or use ESCAPE:
SELECT *
FROM YourTable
WHERE coupon_name LIKE '%50\%%' ESCAPE '\'
Or:
SELECT *
FROM YourTable
WHERE coupon_name LIKE '%50|%%' ESCAPE '|'
The third one should work in MySQL and SQL Server.
Let me describe the problem based on the example below.
Lets say there is a string "abc12345" (could be any!!!) and there is a table mytable with a column mycolumn of varchar(100).
There are some rows that ends with the last character 5.
There are some rows that ends with the last characters 45.
There are some rows that ends with the last characters 345
There are no rows that ends with the last characters 2345.
In this case these rows should be selected:
SELECT * FROM mytable WHERE mycolumn LIKE "%345"
That's because "345" is the longest right substring of "abc12345" that occurs at least once as the right substring of at least one string in the mycolumn column.
Any ideas how to write it in one query?
Thank you.
This is a brute force method:
select t.*
from (select t.*,
dense_rank() over (order by (case when mycolumn like '%abc12345' then 1
when mycolumn like '%bc12345' then 2
when mycolumn like '%c12345' then 3
when mycolumn like '%12345' then 4
when mycolumn like '%2345' then 5
when mycolumn like '%345' then 6
when mycolumn like '%45' then 7
when mycolumn like '%5' then 8
end)
) as seqnum
where mycolumn like '%5' -- ensure at least one match
from t
) t
where seqnum = 1;
This then inspires something like this:
select t.*
from (select t.*, max(i) over () as maxi
from t join
(select str, generate_series(1, length(str)) as i
from (select 'abc12345' as str) s
) s
on left(t.mycolumn, i) = left(str, i)
) t
where i = maxi;
Interesting puzzle :)
The hardest problem here is finding what is the length of the target suffix matching your suffix pattern.
In MySQL you probably need to use either generating series or a UDF. Others proposed these already.
In PostgreSQL and other systems that provide regexp-based substring, you can use the following trick:
select v,
reverse(
substring(
reverse(v) || '#' || reverse('abcdefg')
from '^(.*).*#\1.*'
)) res
from table;
What it does is:
constructs a single string combining your string and suffix. Note, we reverse them.
we put # in between the strings that's important, you need a character that doesn't exist in your string.
we extract a match from a regular expression, using substring, such that
it starts at the beginning of the string ^
matches any number of characters (.*)
can have some remaining characters .*
now we find #
now, we want the same string we matched with (.*) to be present right after #. So we use \1
and there can be some tail characters .*
we reverse the extracted string
Once you have the longest suffix, finding maximum length, and then finding all strings having the suffix of that length is trivial.
Here's a SQLFiddle using PostgreSQL:
If you cannot restructure the table I would approach the problem this way:
Write an aggregate UDF LONGEST_SUFFIX_MATCH(col, str) in C (see an example in sql/udf_example.c in the MySQL source, search for avgcost)
SELECT #longest_match:=LONGEST_SUFFIX_MATCH(mycol, "abcd12345") FROM mytbl; SELECT * FROM mytbl WHERE mycol LIKE CONCAT('%', SUBSTR("abcd12345", -#longest_match))
If you could restructure the table, I do not have a complete solution yet, but the first thing I would add a special column mycol_rev obtained by reversing the string (via REVERSE() function) and create a key on it, then use that key for lookups. Will post a full solution when I have a moment.
Update:
If you can add a reversed column with a key on it:
use the query in the format of `SELECT myrevcol FROM mytbl WHERE myrevcol LIKE CONCAT(SUBSTR(REVERSE('$search_string'), $n),'%') LIMIT 1 performing a binary search with respect to $n over the range from 1 to the length of $search_string to find the largest value of $n for which the query returns a row
SELECT * FROM mytbl WHERE myrevcol LIKE CONCAT(SUBSTR(REVERSE('$search_string'), $found_n),'%')
This solution should be very fast as long as you do not have too many rows coming back. We will have a total of O(log(L)) queries where L is the length of the search string each of those being a B-tree search with the read of just one row followed by another B-tree search with the index read of only the needed rows.
Hello everyone as the topic says I am looking for alternative or advanced using of "LIKE".
I have column which contains a row of words p.e. "keyword1,keyword2,another_keyword" and when I use
$sql = mysql_query("SELECT * FROM table WHERE `column` LIKE '%keyword1%' ");
It hardly find it p.e. this example works but when i try to find shorter strings it has problems and sometimes it does not find anything.
I tried put a whitespace after comas and it helped but if there is a way where I can search for match with this specification of column I would be happy.
You may move keywords into individual table.
Or you can use SET field type, if the list of your keywords don't change.
Storing comma separated list of your words is a bad idea example using like in your scenario is hard to find the exact work in comma separated list instead you can add new table which relates to your current table and store each the word in a new row with the associated identity like
table1
id title
1 test1
2 test2
kewords_table
table1_id word
1 word1
1 word2
1 word3
and query will be
select t.*
from table1 t
join kewords_table k
on(t.id = k.table1_id)
where k.word = 'your_keyword'
If you can't alter your structure you can use find_in_set()
SELECT * FROM table WHERE find_in_set('your_keyword',`column`) > 0
try something like this:
SELECT * FROM tablename
WHERE column LIKE '%keyword1%'
OR column LIKE '%keyword2%';
for more info see here:Using SQL LIKE and IN together
MySQL allows you to perform a full-text search based on very complex queries in the Boolean mode along with Boolean operators. This is why the full-text search in Boolean mode is suitable for experienced users.
First You have to add FULLTEXT index to that perticuler column :
ALTER TABLE table_name ADD search_column TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, ADD FULLTEXT search_column (search_column);
Run following query for searching :
SELECT * FROM table WHERE MATCH(search_column) AGAINST("keyword1")
for more info see here : https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html