MySQL select column string with LIKE or REGEX based on sub-string with delimiters - mysql

I have to compare a column value with a user input numbers. The string in the column is in the format 8|5|12|7|
Now, I need to compare a user input values 2,5,3 with this column value
When I use LIKE operator as '%2|%' I got the output by matching with column value |12|
How do I match the string by using Regular Expression or any other way?

If I understand the question correct, then to make sure that you get 2|.. or ..|2|.. or |2, you need to add or clauses
where col like '%|2|%'
or col like '2|%'
or col like '%|2'
or col='2'

Something similar to this to test for 2 in this example 12|8|12|5|12|7|2|12|22
# (^|\|)2(\||$)
#
#
# Match the regex below and capture its match into backreference number 1 «(^|\|)»
# Match this alternative (attempting the next alternative only if this one fails) «^»
# Assert position at the beginning of the string «^»
# Or match this alternative (the entire group fails if this one fails to match) «\|»
# Match the character “|” literally «\|»
# Match the character “2” literally «2»
# Match the regex below and capture its match into backreference number 2 «(\||$)»
# Match this alternative (attempting the next alternative only if this one fails) «\|»
# Match the character “|” literally «\|»
# Or match this alternative (the entire group fails if this one fails to match) «$»
# Assert position at the end of the string, or before the line break at the end of the string, if any (line feed) «$»
REGEXP "(^|\|)2(\||$)"
This allows for the column value to just be 2 or 2|anything or anything|2 or first thing|2|end thing.

By looking your column design, one of the way u can do is LIKE '%|2|%'

It is bad design to build "arrays" in a cell. Use a separate table.
Anyway, FIND_IN_SET() is a function that does the work a lot easier than a regexp. (But you have to use ',')

Related

MySQL LIKE Operator with Special Characters Confusion

First let me apologize I have not been successful in finding anything online with this specific scenario.
I have been using MySQL for quite some time, but I am hoping to get some clarification on a certain situation I have come across, which honestly bothers me quite a bit.
I'm trying to match a string in a MySQL column that contains both \ and % literal characters using the LIKE operator.
Inside the table I have two records:
id value
-----------------------
1 100\\%A
2 100\%A
They both contain literal special characters.
If I do a SELECT, in an attempt to only match the first record (id=1), I would expect to write the query as such:
SELECT * FROM table_name WHERE value LIKE '%0\\\\\%A'
(\\\\ to match two literal backslashes, plus a backslash before % to match a literal %)
However, It only matches the row (id=2), which makes no sense to me.
If I change the query a little to be:
SELECT * FROM table_name WHERE value LIKE '%0\\\\%A'
I would expect to match the id=1 row only, (\\\\ to match 2 literal backslashes, and the % is not literal and should represent a wildcard). But instead, it matches both rows?
row (id=2) only has a single backslash but still matches.
Is row id=2 matching because the first 2 backslashes are matching the \, the 3rd backslash is ignored for some reason, and the 4th backslash is allowing a literal match on the %?
If I do a:
SELECT * FROM table_name WHERE value LIKE '%0\\\\\\\%A'
I for some reason get row (id=1), when I would expect to get no matches whatsoever.
I'm trying to find a solution in which I can do partial matches on any series of characters accurately, including those with consecutive special characters such as the scenario above. However, I'm having an impossible time trying to plan for situations such as these.
Any input would be greatly appreciated.
Maybe this help you understand the usage of escape chars in mySQL
https://stackoverflow.com/a/27061961/634698

multiline filebeat pattern to match miltiple word

Some confusion here where I have to use filebeat multiline pattern to collec data.
Question is how to use multiple pattern ?
Here what i use now
multiline.pattern : '^Select'
So for above pattern we can see all word start from select will be match. So my question how about INSERT,UPDATE and DELETE word ?
Also one question can I use below pattern to indicate end of multiline match ?
multiline.flush_pattern: ';'
Any idea or help is highly appreciated
To your first question:
You can specify multiple words for the beginning of the message within a single regex. So if I understood you correctly, you want to include all log lines that start with Select, INSERT, UPDATE and DELETE. To achieve this you would define a group of valid values like so:
multiline.pattern : '^(Select|INSERT|UPDATE|DELETE)
The pipe-character ( | ) acts as an OR-Operator. Please note that by default regex is case sensitive. So e.g. messages that start with an uppercase SELECT would be ignored in the sample above.
To your second question:
Besides multiline.pattern you have to specify the settings multiline.match and multiline.negate:
multiline.match determines if the log lines before or after the pattern should be put into a single event.
multiline.negate determines if the following lines have to match the pattern.
So instead of specifying a particular end-character you tell Filebeat that every log line that matches the pattern AND is following that line should get aggregated UNTIL the following line matches again the pattern.
(See https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html for a full reference and description).
Example:
Assuming your log file is structured as following:
Select foo from bar\n where baz = 1\n and id =4711;\n\n
DELETE from bar\n where baz = null;\n\n
INSERT ...
the following config should do the job:
multiline.pattern : '^(Select|INSERT|UPDATE|DELETE)'
multiline.match: after
multiline.negate: true
I hope I could help you.

MySQL - search for patterns

I'm trying to figure out if someone has an elegant way to look for patterns in data stored in a varchar field where a value is not known -- meaning I can't use LIKE. For example, say a table called test looked like this:
id, str
and the data looked like this:
1, YUUUY
2, DDDMM
3, MMMMT
4, XMXMX
and I want to do a select that will return anything where the value of str has a pattern that matches the pattern ABABA. ABABA here shows a pattern and not literal letters. So the only one that matches this pattern would be id = 4. Is there a regular expression that I can use to pattern match like this? To make sure I'm clear regarding the patterns:
The pattern for id=1 is ABBBA.
The pattern for id=2 is AAABB.
The pattern for id=3 is AAAAB.
When running the query, all I will know is the pattern to search for.
Alternatively, if it makes it easier, I can have the table set up like:
id,c1,c2,c3,c4,c5
and the data would look like this:
1,Y,U,U,U,Y
2,D,D,D,M,M
3,M,M,M,M,T
4,X,M,X,M,X
Not sure if that makes it easier, but I think regexp is out the window if the data is set up like that.
No regular expression support in MySQL to do that kind of pattern matching, no.
SQL wasn't specifically designed for pattern matching of strings (or patterns of values in separate columns.)
But... we could come up with something workable, even if it's not a regular expression and it's not elegant.
Assuming we don't have a custom built user-defined function, and we want to use native MySQL functions and expression...
And assuming that the patterns we are looking for are guaranteed to consist of only two distinct characters...
And assuming that we're looking at exactly five character positions...
And assuming that the pattern string we're matching to will always begin with the letter 'A', and the "other" letter in the pattern will also be 'B'
It wouldn't be overly ugly to do something like this:
SELECT t.id
, t.str
FROM myable t
WHERE CONCAT('A'
,IF(MID(t.str,2,1)=MID(t.str,1,1),'A','B')
,IF(MID(t.str,3,1)=MID(t.str,1,1),'A','B')
,IF(MID(t.str,4,1)=MID(t.str,1,1),'A','B')
,IF(MID(t.str,5,1)=MID(t.str,1,1),'A','B')
) = 'ABBBA'
The first character in the string is automatically converted to an 'A'.
The second character, if that matches the first character, then it's also an 'A' otherwise it's a 'B'.
We do the same thing for the third, fourth and fifth characters.
Concatenate the 'A' and 'B' characters into a single string, and we can now perform an equality comparison to a pattern string, consisting of 'A' and 'B', starting with an 'A'.
But that is going to fall apart if the stated assumptions aren't true. If str is less than five characters in length, if it contains more than two distinct characters (we'll see the first character as matching... this would see str=XYYZX as matching pattern ABBBA. (First character is automatic match to A, and the fifth character matches the first, so it's an A, and all of the other characters don't match, so they are 'B', even though they aren't the same.
And so on.
We could add some additional checks.
For example, to guaranteed that str is exactly five characters in length...
AND CHAR_LENGTH(t.str)=5
Note that the default collation in MySQL is case insensitive. That means means a str value of MmmmM would be converted to 'AAAAA', not 'ABBBA'. And a str value of MmmKk would match 'AAABB'.
Unfortunately, it doesn't look like MySQL supports regex groups. I was hoping you could do something like this to match ABBBA for example:
([A-Z])([A-Z])\2\2\1
Example here: http://regexr.com/3d8gu
It looks like there is a MySQL plugin that might support it:
https://github.com/mysqludf/lib_mysqludf_preg
Here is a real hacky way to do it.
ABBBA (or YUUUY, etc):
SELECT id, name FROM table WHERE
substring(name,1,1) = substring(name,5,1) AND
substring(name,2,1) = substring(name,3,1) AND
substring(name,3,1) = substring(name,4,1);
AAABB (or DDDMM, etc):
SELECT id, name FROM table WHERE
substring(name,1,1) = substring(name,2,1) AND
substring(name,2,1) = substring(name,3,1) AND
substring(name,4,1) = substring(name,5,1);
AAAAB (or MMMMT, etc):
SELECT id, name FROM table WHERE
substring(name,1,1) = substring(name,2,1) AND
substring(name,2,1) = substring(name,3,1) AND
substring(name,3,1) = substring(name,4,1) AND
substring(name,4,1) != substring(name,5,1);
You get the picture...
It would be similar if you separated the data into different columns. Instead of comparing substrings you would just compare the columns.

How to get results with only numbers and slash

In db I have strings like so
324/23/235 -> all numbers and slashes
and
fsg/23/234 -> NOT all numbers and slashes
Now when I am in desgin view currently the criteria for this column is
>"0"
how can I also add to Find just the strings that have all numbers and slashes?
In Design View, I used this as the criteria for my text column.
Not Like "*[!0-9/]*"
Switching from Design to SQL View displayed this statement.
SELECT tblFoo.some_text
FROM tblFoo
WHERE (((tblFoo.some_text) Not Like "*[!0-9/]*"));
To understand that Like pattern, first consider this one ...
"*[0-9]*"
That matches any single character which is included in the character range 0 through 9. To match either those digits or a slash, include a slash in the range pattern ...
"*[0-9/]*"
However, those are not the characters you're concerned with. You want to target characters other than those included in the range. So you can "negate" the range by using ! in the first position.
"*[!0-9/]*"
So then Like "*[!0-9/]*" would give you rows whose text field string values contain any character other than 0 thru 9 or /. But you want the opposite --- those which do not contain any other character --- so include Not to make the final criteria Not Like "*[!0-9/]*"
The Replace function will remove the slashes and replace with and empty space. IsNumeric will return a Boolean = True if the remaining characters can be converted successfully to an number.
Select * from [TableWithStrings] as t
where IsNumeric(Replace(t.[FieldWithTheseStrings], "/", ""))=True;
These functions could be used in code as well as your view.

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.