REPLACE function not working on SELECT using an INNER JOIN - mysql

I can't get the REPLACE function to work on my SQL command shown here. I want it to take my search term (55512) and search for this in the field using the modified field from the regexp to remove all non-alphanumeric fields.
SELECT
`Customers`.`id` AS `Customers__id`,
`Contact`.`id` AS `Contact__id`,
`Contact`.`customer_id` AS `Contact__customer_id`,
`Contact`.`full_name` AS `Contact__full_name`,
`Contact`.`phones` AS `Contact__phones`
FROM
`customers` `Customers`
INNER JOIN `contacts` `Contact` ON `Contact`.`id` = (`Customers`.`contact_id`)
WHERE
REPLACE(
`Contact`.`phones`, "[^a-zA-Z0-9]",
""
) LIKE '%55512%'
LIMIT
20 OFFSET 0
So what I want to do is be able to search "55512" and have it match if the Contact.phones field contains "999-555-1212" or "(999) 555-1212". The Contact.phones field is stored as a JSON array in case this is relevant, but I would expect the above SQL command to remove all brackets, curly braces, etc and just search for the string.
When I do the above search in MySQL, it returns zero results, but there is a result that contains: [{"value":"999-555-1212","label":"Primary"}]

The problem is that the REPLACE function does not work with regex, but attempts to match strings.
You can solve this problem in two ways:
adopting REGEXP_REPLACE function, that effectively uses regex:
WHERE
REGEXP_REPLACE(
`Contact`.`phones`, "[^a-zA-Z0-9]",
""
) LIKE '%55512%'
keeping the REPLACE function, but replacing dashes only with the empty string.
WHERE
REPLACE(
`Contact`.`phones`, "-",
""
) LIKE '%55512%'
Check the demo here.

WHERE phones RLIKE '555-?12'
Would also work since the only extraneous characters would be a dash in one spot.
Both this and the answer from lemon will require a full table scan. That is, either will be slow if the table is big.

Related

How to replace strings in MySQL that contains backslashes

I try to replace strings in MySQL table from:
href=\"example.com\"
to
href=\"https://example.com\"
I know correct query how to search and update string, it is works perfectly, until I try to change string with backslashes. Nothing doesn't work:
UPDATE `articles` SET `text` = REPLACE(`text`, 'href=\\\\"example.com\\\\"', 'href=\\\\"https://example.com\\\\"') WHERE `text` LIKE '%href=\\\\"example.com\\\\"%'
Of course I tried different variants and combinations with escaped and not escaped backslaches, with clause WHERE and without it. These all variants doesn't work. Nothing changes at all!
Also, when I pre-run this query in PHPMyAdmin (section "Find and Replace"), it correctly finds all articles that contains href=\"example.com\", but Replaced string shows me the same content as Original String.
My CMS, which has also built-in function for search and replace strings, also can't change strings with backslashes.
I'm totally stuck with this problem.
You put too much backslash on the replace search string so the string is not found. double backslash are stored as one backslash in the table, so you need to use 2x backslash when replacing the string and 4x backslash when doing search in where clause.
see demo here; http://sqlfiddle.com/#!9/c1e0eb/1
update articles
set text =
REPLACE(`text`, 'href=\\"example.com\\"', 'href=\\"https://example.com\\"')
where text like '%href=\\\\"example.com\\\\"%'
This is the query you want to update;
UPDATE `articles`
SET `text` = REPLACE(`text`, 'href=\\"example.com\\"', 'href=\\"https://example.com\\"')
WHERE `text` LIKE '%href=\\\\"example.com\\\\"%'

REGEX to Find Rows Containing Opening and Closing Parentheses in MySQL

I have tried:
....WHERE fieldname REGEXP '.*\(.*\).*';
But this returns every record in the table.
You should use double backslashes when escaping a regex special metacharacter in a REGEXP pattern. Also, since REGEXP also finds partial matches, you do not need the .* at the start/end.
So, you could fix the expression as
WHERE fieldname REGEXP '\\(.*\\)';
Or just use LIKE where % matches any amount of arbitrary chars (but must match the whole entry unlike REGEXP):
WHERE fieldname LIKE '%(%)%';
A MySQL fiddle:
DROP TABLE IF EXISTS t;
CREATE TABLE t (word varchar(255));
INSERT INTO t (word)
VALUES
('test (here)'),
('test (here) test'),
('(here) test'),
('test no'),
('no test');
SELECT * FROM t WHERE word REGEXP '\\(.*\\)';
SELECT * FROM t WHERE word LIKE '%(%)%';
To get entries like text ) and ( here, you may use
SELECT * FROM t WHERE word REGEXP '\\(.*\\)|\\).*\\(';
SELECT * FROM t WHERE word LIKE '%(%)%' OR word LIKE '%)%(%';
See another fiddle.
LIKE would be more efficient than REGEXP, but to answer in REGEXP terms...
I suspect the OP wants parentheses to be somewhere in the middle of row text.
The problem with the REGEXP supplied is that expressions are greedy.
As soon as the .* finishes matching, it has already soaked up the entire record.
Try making the first two .* expressions as [^(]( and [^)]) and removing the final .* as it is superfluous.
'[^\\(]*\\([^\\)]*\\)'
Basically, this expression says
Look for zero or more non ( characters
then look for a single ( character
then look for zero or more non ) characters
then look for a single ) character
The () may be anywhere in the record and may contain zero or more characters inside the ().
Might I suggest fiddling in https://regex101.com/
Hope this helps.

Apostrophe in FULL TEXT SEARCH mysql

When I searched for citroen in search page like that I get result but if I search blackn roll I dont get result because it's written like black'n roll in the table. Some user may also wanna search blackn roll but doesnt get result. How can I fix it? And also rows like v-hr and speacial characters like "&/(). I want the mysql to ignore them.
$sql = "SELECT * FROM arac
INNER JOIN suv_marka ON arac.marka = suv_marka.id
WHERE match(suv_marka.marka) against('citroen')";
If you know the characters (to be replaced) already then, you can use MySQL's REPLACE function to replace them with % and perform LIKE comparison, e.g.:
create table test(value varchar(100));
insert into test values ('black''n roll');
SELECT value
FROM test
WHERE 'blackn roll' LIKE CONCAT('%', REPLACE(value, '''', '%'), '%');
You can replace 'blackn roll' with your input string and use nested REPLACE functions if you need to replace more than one character.
The back-slash is MySQL's escape character. You can try the following... Full text indexing gets a little weird because of word terminators.
$sql = "SELECT * FROM arac
INNER JOIN suv_marka ON arac.marka = suv_marka.id
WHERE match(suv_marka.marka) against ('black\'n roll' IN BOOLEAN MODE);"
If that doesn't work, then try looking for the words individually. Word length is also a factor, small words (less than 4 characters by default) are not indexed.
$sql = "SELECT * FROM arac
INNER JOIN suv_marka ON arac.marka = suv_marka.id
WHERE match(suv_marka.marka) against ('black' + 'roll' IN BOOLEAN MODE);"

Using MySQL LIKE operator for fields encoded in JSON

I've been trying to get a table row with this query:
SELECT * FROM `table` WHERE `field` LIKE "%\u0435\u0442\u043e\u0442%"
Field itself:
Field
--------------------------------------------------------------------
\u0435\u0442\u043e\u0442 \u0442\u0435\u043a\u0441\u0442 \u043d\u0430
Although I can't seem to get it working properly.
I've already tried experimenting with the backslash character:
LIKE "%\\u0435\\u0442\\u043e\\u0442%"
LIKE "%\\\\u0435\\\\u0442\\\\u043e\\\\u0442%"
But none of them seems to work, as well.
I'd appreciate if someone could give a hint as to what I'm doing wrong.
Thanks in advance!
EDIT
Problem solved.
Solution: even after correcting the syntax of the query, it didn't return any results. After making the field BINARY the query started working.
As documented under String Comparison Functions:
Note
Because MySQL uses C escape syntax in strings (for example, “\n” to represent a newline character), you must double any “\” that you use in LIKE strings. For example, to search for “\n”, specify it as “\\n”. To search for “\”, specify it as “\\\\”; this is because the backslashes are stripped once by the parser and again when the pattern match is made, leaving a single backslash to be matched against.
Therefore:
SELECT * FROM `table` WHERE `field` LIKE '%\\\\u0435\\\\u0442\\\\u043e\\\\u0442%'
See it on sqlfiddle.
it can be useful for those who use PHP, and it works for me
$where[] = 'organizer_info LIKE(CONCAT("%", :organizer, "%"))';
$bind['organizer'] = str_replace('"', '', quotemeta(json_encode($orgNameString)));

Using REGEX to alter field data in a mysql query

I have two databases, both containing phone numbers. I need to find all instances of duplicate phone numbers, but the formats of database 1 vary wildly from the format of database 2.
I'd like to strip out all non-digit characters and just compare the two 10-digit strings to determine if it's a duplicate, something like:
SELECT b.phone as barPhone, sp.phone as SPPhone FROM bars b JOIN single_platform_bars sp ON sp.phone.REGEX = b.phone.REGEX
Is such a thing even possible in a mysql query? If so, how do I go about accomplishing this?
EDIT: Looks like it is, in fact, a thing you can do! Hooray! The following query returned exactly what I needed:
SELECT b.phone, b.id, sp.phone, sp.id
FROM bars b JOIN single_platform_bars sp ON REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(b.phone,' ',''),'-',''),'(',''),')',''),'.','') = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(sp.phone,' ',''),'-',''),'(',''),')',''),'.','')
MySQL doesn't support returning the "match" of a regular expression. The MySQL REGEXP function returns a 1 or 0, depending on whether an expression matched a regular expression test or not.
You can use the REPLACE function to replace a specific character, and you can nest those. But it would be unwieldy for all "non-digit" characters. If you want to remove spaces, dashes, open and close parens e.g.
REPLACE(REPLACE(REPLACE(REPLACE(sp.phone,' ',''),'-',''),'(',''),')','')
One approach is to create user defined function to return just the digits from a string. But if you don't want to create a user defined function...
This can be done in native MySQL. This approach is a bit unwieldy, but it is workable for strings of "reasonable" length.
SELECT CONCAT(IF(SUBSTR(sp.phone,1,1) REGEXP '^[0-9]$',SUBSTR(sp.phone,1,1),'')
,IF(SUBSTR(sp.phone,2,1) REGEXP '^[0-9]$',SUBSTR(sp.phone,2,1),'')
,IF(SUBSTR(sp.phone,3,1) REGEXP '^[0-9]$',SUBSTR(sp.phone,3,1),'')
,IF(SUBSTR(sp.phone,4,1) REGEXP '^[0-9]$',SUBSTR(sp.phone,4,1),'')
,IF(SUBSTR(sp.phone,5,1) REGEXP '^[0-9]$',SUBSTR(sp.phone,5,1),'')
) AS phone_digits
FROM sp
To unpack that a bit... we extract a single character from the first position in the string, check if it's a digit, if it is a digit, we return the character, otherwise we return an empty string. We repeat this for the second, third, etc. characters in the string. We concatenate all of the returned characters and empty strings back into a single string.
Obviously, the expression above is checking only the first five characters of the string, you would need to extend this, basically adding a line for each position you want to check...
And unwieldy expressions like this can be included in a predicate (in a WHERE clause). (I've just shown it in the SELECT list for convenience.)
MySQL doesn't support such string operations natively. You will either need to use a UDF like this, or else create a stored function that iterates over a string parameter concatenating to its return value every digit that it encounters.