First I want to say, I'm sorry if this question have be asked already (haven't been able to find it then).
My problem is that I've got a LIKE clause in mysql where I have to find some numbers in a comma seperated row.
(Yes I know comma separated rows aint a good thing to use, but I'm not the one who made the database structure).
So I have the following:
SELECT pfd.*, pu.username, pu.user_email
FROM phpbb_profile_fields_data pfd
LEFT JOIN phpbb_users pu ON pfd.user_id=pu.user_id
WHERE pfd.pf_pf_produktionsteknik LIKE '%" . ($id) . "%'
AND pu.user_type!=1 AND pfd.pf_status=2";
But the problem is here that it returns where the LIKE equal 1 (as it should) but also 11 (which it should not).
I have tried using field_in_set wich I couldn't get to work, and I'm now lost at what to do about it.
If your list is comma separated, can you look for number then comma, OR comma then number, or equalling number on its own. That should cover all cases including single number instances.
The value searched for could be embraced by commas or followed by a comma when positioned at the list start or following a comma when positioned at the list end or it is the only value (no commas in the list)
WHERE (pfd.pf_pf_produktionsteknik LIKE '%," . ($id) . ",%'
OR pfd.pf_pf_produktionsteknik LIKE '"($id) . ",%'
OR pfd.pf_pf_produktionsteknik LIKE '%," .($id) . "'
OR pfd.pf_pf_produktionsteknik = '" .($id) . "' ) AND ...
You're dealing with data that's badly structured, so you need to have that addressed -- comma-delimited sets of numbers are not in 1nf, which is pretty basic.
Now that I've got that out of the way, you can try using a regexp instead of LIKE:
As SQL (note the value 1):
WHERE pfd.pf_pf_produktionsteknik REGEXP '\b1\b'
or as a PHP string:
..." WHERE pfd.pf_pf_produktionsteknik REGEXP '\b" . $id . "\b'"
...which will match 1 but not 11: \b is the regex for "word boundary", which means it requires the start of a string or punctuation or whitespace on either side of your value $id.
The find_in_set (manual) mysql function is what you're looking for : it searches a value inside a comma separated value.
select find_in_set('1', 'a,b,1,c');
Gives this :
+-----------------------------+
| find_in_set('1', 'a,b,1,c') |
+-----------------------------+
| 3 |
+-----------------------------+
1 row in set (1.10 sec)
If the function fails, it returns 0.
In your case, doing WHERE find_in_set('1', pfd.pf_pf_produktionsteknik) > 0 will give you what you need.
Related
I have two records with names bowser and Tommy in the table pet. Now when I run the following query in cmd nothing happen:
SELECT * FROM pet WHERE name LIKE '.%';
On the other hand the following query matches Bowser record:
SELECT * FROM pet WHERE name LIKE 'b%';
As far as I know, . should match any character. So '.%' should match every word.
Why is dot metacharactor of regex not working in mysql?
The reason your query doesn't work is because it is looking for names that start with a period. That is how LIKE works.
Use RLIKE or REGEXP:
WHERE name REGEXP '.*';
LIKE uses the ANSI standard for the operator. The equivalent of . is _. However, the way LIKE works is different from regular expressions.
The documentation does a good job of explaining the differences between LIKE and REGEXP.
I am trying to find a string in a MySQL field which is encoded in base64 (for international characters)
Usual search:
$sql = "SELECT * FROM table WHERE field LIKE '%term%' ";
I have tried this:
$sql = "SELECT * FROM table WHERE field name LIKE '%".base64_encode($term)."%' ";
But it does not work all the time, depending on the search term length... For some reason, it gives result whenever my term is an odd-number long...
I have also tried using the MySQL function TO_BASE64() and FROM_BASE64() which did not work...
Can someone please help?
You need to compare the input value against the base64-decoded stored value, so reverse your attempt a little to call FROM_BASE64() on the stored value and compare against the plain input value. You cannot compare a partial match in $term if it is encoded because the partial value will never produce the same or even similar base64 string as the full stored value.
SELECT * FROM `table` WHERE FROM_BASE64(`field`) LIKE '%$term%'
In this context, $term is a plain string, not base64 encoded. It's of course recommended that $term be a bound parameter rather than a plain PHP variable concatenated into the query.
However, this is going to be slow. If you are in any position to change the way your data has been stored, you are highly encouraged to store it in a plain unencoded form. Every query will need to base64-decode every row to find a matching one, which is extremely inefficient.
Note also, that TO_BASE64(),FROM_BASE64() were recently added in MySQL 5.6.1, and therefore may not be available in a lot of installations. You really should change the way the data is stored to eliminate the encoding.
If you don't want to upgrade to MySQL 5.6 or above, you can use the following trick which is removing the padding issue:
SELECT * FROM `table` WHERE
field LIKE '%" . base64_encode($term) . "%'
OR field LIKE '%" . substr(base64_encode($term .'a'),0,-4) . "%'
OR field LIKE '%" . substr(base64_encode($term .'aa'),0,-8) . "%'
OR field LIKE '%" . substr(base64_encode($term .'aaa'),0,-12) . "%'
The search term length issue is therefore avoided. You may optimize this query by using only one of the four LIKE depending on the length of the $term.
let's say I have a string in which the words are separated by 1 or more spaces and I want to use that string in and SQL LIKE condition. How do I make my SQL and tell it to match 1 or more blank space character in my string? Is there an SQL wildcard that I can use to do that?
Let me know
If you're just looking to get anything with atleast one blank / whitespace then you can do something like the following WHERE myField LIKE '% %'
If your dialect allows it, use SIMILAR TO, which allows for more flexible matching, including the normal regular expression quantifiers '?', '*' and '+', with grouping indicated by '()'
where entry SIMILAR TO 'hello +there'
will match 'hello there' with any number of spaces between the two words.
I guess in MySQL this is
where entry RLIKE 'hello +there'
I know this is late, but I never found a solution to this in relation to a LIKE question.
There is no way to do what you're wanting within a SQL LIKE. What you would have to do is use REGEXP and [[:space:]] inside your expression.
So to find one or more spaces between two words..
WHERE col REGEXP 'firstword[[:space:]]+secondword'
Another way to match for one or more space would be to use [].
It's done like this.
LIKE '%[ ]%'
This will match one or more spaces.
you can't do this using LIKE but what you can do, if you know this condition can exist in your data, is as you're inserting the data into the table, use regular expression matching to detect it up front and set a flag in a different column created for this purpose.
I just replace the whitespace chars with '%'. Lets say I want to do a LIKE query on a string like this 'I want to query this string with a LIKE'
#search_string = 'I want to query this string with a LIKE'
#search_string = ("%"+#search_string+"%").tr(" ", "%")
#my_query = MyTable.find(:all, :conditions => ['my_column LIKE ?', #search_string])
first I add the '%' to the start and end of string with
("%"+#search_string+"%")
and then replace other remaining whitespace chars with '%' like so
.tr(" ", "%")
http://www.techonthenet.com/sql/like.php
The patterns that you can choose from are:
% allows you to match any string of any length (including zero length)
_ allows you to match on a single character
I think that the question is not asking to match any spaces but to match two strings one a pattern and the other with wrong number of spaces because of typos.
In my case I have to check two fields from different tables one preloaded and the other filled typed by users so sometimes they don't respect 100% the pattern.
The solution was to use LIKE in the join
Select table1.field
from table1
left join table2 on table1.field like('%' + replace(table2.field,' ','%')+'%')
if the condition:
WHERE myField LIKE '%Hello world%'
doesn't work try
WHERE myField LIKE '%Hello%'
and
WHERE myField LIKE '%world%'
this approach is helpful in a few specific use cases, hope this helps.
I have a table that contains a text field, there is around 3 to 4 sentences in the field depending on the row.
Now, I am making an auto-complete html object, and I would like to start typing the beginning of a word and that the database return words that start with those letters from the database text field.
Example of a text field: I like fishsticks, fishhat are great too
in my auto-complete if I would type "fish" it would propose "fishsticks" and "fishhat"
Everything works but the query.
I can easily find the rows that contains a specific word but I can't extract only the word, not the full text.
select data_txt from mytable match(data_txt) against('fish', IN BOOLEAN MODE) limit 10
I know it is dirty, but I cannot rearrange the database.
Thank you for your help!
EDIT:
Here's what I got, thanks to Brent Worden, it is not clean but it works:
SELECT DISTINCT
SUBSTRING(data_txt,
LOCATE('great', data_txt),
LOCATE(' ' , data_txt, LOCATE('great', data_txt)) - LOCATE('great', data_txt)
)
FROM mytable WHERE data_txt LIKE '% great%'
LIMIT 10
any idea on how to avoid using the same LOCATE expression over and over?
Use LOCATE to find the occurrence of the word.
Use LOCATE and the previous LOCATE return value to find the occurrence of the first space after the word.
USE SUBSTR and the previous 2 LOCATE return values to extract the whole word.
$tagsql ="SELECT * from mytable";
$tagquery = mysql_query($tagsql);
$tags = array(); //Creates an empty array
while ($tagrow = mysql_fetch_array($tagquery)) {
$tags[] = tagrow['tags']; //Fills the empty array
}
If the rows contain commas you could use -
$comma_separated = implode(",", $tags);
you can replace the comma for spaces if they are separated as spaces in your table.
$exp = explode(",", $comma_separated);
If you require your data to be unique you may include the following:
$uniquetags = array_unique($exp, SORT_REGULAR);
you can use print_r to see the results of the array resulting
Here array_merge is used because $rt will not get displayed if you are using a 'jquery' autocomplete else $rt may work and array_merge can be ignored. However, you may use array_merge to include multiple tables by repeating the previous process.
$autocompletetags = array_merge((array)$uniquetags);
This sorts the values in the alphabetic order
sort($autocompletetags, SORT_REGULAR);
I need to make a selection based on the first 2 characters of a field, so for example
SELECT * from table WHERE postcode LIKE 'rh%'
But this would select any record that contains those 2 characters at any point in the "postcode" field right? I am in need of a query that just selects the first 2 characters. Any pointerS?
Thanks
Your query is correct. It searches for postcodes starting with "rh".
In contrast, if you wanted to search for postcodes containing the string "rh" anywhere in the field, you would write:
SELECT * from table WHERE postcode LIKE '%rh%'
Edit:
To answer your comment, you can use either or both % and _ for relatively simple searches. As you have noticed already, % matches any number of characters whereas _ matches a single character.
So, in order to match postcodes starting with "RHx " (where x is any character) your query would be:
SELECT * from table WHERE postcode LIKE 'RH_ %'
(mind the space after _). For more complex search patterns, you need to read about regular expressions.
Further reading:
http://dev.mysql.com/doc/refman/5.1/en/pattern-matching.html
http://dev.mysql.com/doc/refman/5.1/en/regexp.html
LIKE '%rh%' will return all rows with 'rh' anywhere
LIKE 'rh%' will return all rows with 'rh' at the beginning
LIKE '%rh' will return all rows with 'rh' at the end.
If you want to get only first two characters 'rh', use MySQL SUBSTR() function
http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substr
Dave, your way seems correct to me (and works on my test data). Using a leading % as well will match anywhere in the string which obviously isn't desirable when dealing with postcodes.