Advanced MySQL pattern matching (beyond LIKE...%) - mysql

This is the example of my current MySQL my_table...
id name code
1 111 XXXX123456XXXXXXXXXXXXXX
2 222 XXXX133456XXXXXXX5XXXXXX
3 333 XXXX123454XXX11XXXXXXABC
Code is a 24 character hexadecimal value where X is the wildcard.
I need to write a query that will return the NAME based on the CODE without a wildcard value X.
The given CODE value will be exact but it should compare the string in place, X could match any character.
For example:
SELECT name FROM my_table where code = '012312345611111111111111';
name
111
SELECT name FROM my_table where code = '000013345622222225123456';
name
222
SELECT name FROM my_table where code = '000123454ABC11234567FABC';
name
333

You can use like for this. Are you aware of the _ wildcard?
select t.*
from t
where #YourCode like replace(t.code, 'X', '_');
Of course, you can use regular expressions too. The regular expression would be: concat('^', replace(t.code, 'X', '.'), '$').

Related

Compairing two strings in MYSQL

I have a sequence of 20 numbers from 0 to 2, I want to compare this string with other sequences saved in my database, the problem is that the lenght of the strings saved on the database fluctuates.Also the comparison needs to be done from the end to the start.
Example of what I want:
20 digits string:
'1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1'
couple of strings saved in the database:
1 - '1,1,2,1'
2 - '2,1,2,2,2,2'
3 - '2,1'
4 - '1,1,2,1,2,1'
In this case the query would return the 1 and 3 only
create table mytable ( s varchar(60) );
insert into mytable values
('1,1,2,1'),
('2,1,2,2,2,2'),
('2,1'),
('1,1,2,1,2,1');
set #x = '1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1';
select s from mytable
where right(#x, length(s)) = s;
Output:
s
1,1,2,1
2,1
Fiddle: https://www.db-fiddle.com/f/r5m2hPbnmUu5VQfYvMVtir/0
You could use a LIKE trick here. For example, to check for the first string 1,1,2,1:
SELECT *
FROM yourTable
WHERE ',1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1,' LIKE '%,1,1,2,1,%';

Return strings which contains number on specific position

I am basic on SQL queries and I need some help.
I have to select all string values which contains number e.g. 7 only on specific position in that string.
For example:
I have string: 987654321 and if on position 3 I will have number 7, then it should be selected.
So in example this string will be selected, because on 3rd position I have number 7.
Is there any SQL function for that, or something which could help me?
EDIT:
Example table
TABLE
Numbers Value
987654321 1
123456789 2
789009871 3
654321092 4
847949372 5
Output:
TABLE
Numbers Value
987654321 1
847949372 5
Statement:
SELECT table.numbers
FROM TABLE
WHERE substr(table.numbers,3,1)='7' <--- what to do here? --->
Many thanks in advance.
For a regex option, you may use MySQL's REGEXP operator:
SELECT *
FROM yourTable
WHERE num REGEXP '^[0-9]{2}7';
On Oracle, you could use REGEXP_LIKE:
SELECT *
FROM yourTable
WHERE REGEXP_LIKE(num, '^[0-9]{2}7');
You should use case statement.
select case when substr(stringcol, 3,1) = '7' then stringcol else "not valid" end as stringcol from <Table Name>

I need to display the data, if at least one string present in another column using SQL

I have two columns in a table, column 1 contains tom jerry and column 2 has tom xxxx . I need to fetch the row at least one string is present the other column data
column1 column2
-----------------------------
tom jerry : tom xxx
tiger : tom yyy
tiger lion : lipard
lion tom : tiger lion
23 : 235 452
23 : 23
Expected result:
column1 column2
---------------------------
tom jerry : tom xxx
lion tom : tiger lion
23 : 23
Here is my approach:
Put both columns to another table with identity column (to identify each row)
Write a function to split text by a string (in this case pass a space)
Here you can use built in function if it is higher than SQL Server 2016
Get the identity and the splitted data to 2 tables each for column 1 and 2
Join the 2 tables for matches in Col-Split data, and get the IDs
Now Query for the data in table in above 1
Here is the Fiddle assuming that the code is for SQL Server 2016
In MySQL, you can use a regular expression for the data you have presented:
where column1 regexp replace(column2, ' ', '|') or
column2 regexp replace(column1, ' ', '|')
This may or may not work as stated. For instance, this will match "lion" and "lions" -- that meets what you are describing as I read it. That said, you can modify the patterns to enforce word breaks if you have something slightly different in mind.
You'd be able to achieve this by creating a function wherein you will pass value of column1 and column2. The function will do the heavy-lifting of checking if column1 value (multiple words separated by whitespace) has any of its word matching in column2 value. The pseudo code of function should be something like this -
Function bool IsCol1WordPresentInCol2(varchar2 col1value, varchar2 col2value)
Step 1: Split col1value based on whitespace to get series of words
Step 2: Split col2value based on whitespace to get series of words
Step 3: Outer loop to iterate through all words of col1 (extracted from step 1)
Step 4: Inner loop to iterate through all words of col2 (extracted from step 2)
Step 5: Check if the col1 and col2 words do match. At any point, if any match is found, return true from the function; else false.
Step 6: Based on the returned bool value from this function, you'd be able to identify, in your calling logic, if that record satisfies your condition.
You can use instring function to achieve this. Function depends on the database you use. Below is the query,
select * from table1 where col1 > col2;
select distinct t1.* from table1 t1
inner join table1 t2
on (instr(substring(t1.col1, instr(t1.col1, ' ') -1), col2) > 0);

MySQL strange behavior when comparing comma-separated string with number

I am experiencing some weird behavior with MySQL. Basically I have a table like this:
ID string
1 14
2 10,14,25
Why does this query pull id 2?
SELECT * FROM exampletable where string = 10
Surely it should be looking for an exact match, because this only pulls id 1:
SELECT * FROM exampletable where string = 14
I am aware of FIND_IN_SET, I just find it odd that the first query even pulls anything. Its behaving like this query:
SELECT * FROM exampletable where string LIKE '10%'
When you compare a numeric and a string value, MySQL will attempt to convert the string to number and match. Number like strings are also parsed. This we have:
SELECT '10,14,25' = 1 -- 0
SELECT '10,14,25' = 10 -- 1
SELECT 'FOOBAR' = 1 -- 0
SELECT 'FOOBAR' = 0 -- 1
SELECT '123.456' = 123 -- 0
SELECT '123.456FOOBAR' = 123.456 -- 1
The behavior is documented here (in your example it is the last rule):
...
If one of the arguments is a decimal value, comparison depends on the
other argument. The arguments are compared as decimal values if the
other argument is a decimal or integer value, or as floating-point
values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point
(real) numbers.

How to: Select from MYSQL text field type only the numbers that start with 89 using REGEXP?

I have tried in many ways to select from text fields only the numbers that start with 89. I don't have a fix length after the first 2 numbers.
How can I do this to work properly and not get numbers like 389xxxxxx in results, for example. THE minimum length should be at least 8 characters.
Thank you!
If your column is integer, then you can probably do something like:
select * from my_table where cast(int_column) as char) like '89______%'
(that's 6 underscore characters before the percentage char)
If it's character value, then you can do this:
SELECT * FROM mytable WHERE char_column REGEXP "^89[[:digit:]]{6,}$"
If your column is numeric with decimal places and you want only integer values, then you need to do something like
SELECT * FROM mytable WHERE cast(numeric_column as char) REGEXP "^89[[:digit:]]{6,}$"
Edit: It seems Tim has edited his answer, which I referred to, so I edited my answer to include his code for column of character type.
SELECT * FROM foo WHERE bar REGEXP "([^0-9]89[0-9]*)|(^89[0-9]*)"
SELECT * FROM mytable WHERE mycolumn REGEXP "(^|[^[:digit:]])89[[:digit:]]{6,}";
will do this:
( # Either match
^ # the start of the string
| # or
[^[:digit:]] # any character except a digit
) # End of alternation.
89 # Match 89
[[:digit:]]{6,} # plus at least 6 more digits.