MySQL Get the integer value between two strings - mysql

I am trying to get the integer value between two specific strings but I am stacked a little bit.
Example full string:
"The real ABC4_ string is probably company secret."
I need to get the "4" between "ABC" and "_". First I've came up with following script:
select substring_index(substring_index('The real ABC4_ string is probably company secret.', 'ABC', -1),'_', 1);
It gives me 4, perfect! But the problem is if ABC occurs more than one time in the string it fails. I can't simply increase the counter also since I don't know how many times it will be in the future. I have to get first occurrence of that regex: ABC[DIGIT]_
I've seen REGEXP_SUBSTR function but since we use older version of MySQL than 8.0 I can't use it also.
Any suggestions?
Thanks!

Without using Regex, here is an approach using LOCATE(), and other string functions:
SET #input_string = 'The real ABC4_ string is probably company secret.';
SELECT TRIM(LEADING 'ABC'
FROM SUBSTRING_INDEX(
SUBSTR(#input_string FROM
LOCATE('ABC', #input_string)
)
,'_', 1
)
) AS number_extracted;
| number_extracted |
| ---------------- |
| 4 |
View on DB Fiddle

Another way of (ab)using the LOCATE() function:
select substr('The real ABC4_ string is probably company secret.',
locate('ABC', 'The real ABC4_ string is probably company secret.') + 3,
locate('_','The real ABC4_ string is probably company secret.') -
locate('ABC', 'The real ABC4_ string is probably company secret.') - 3) AS num;

Related

SQL Is there a way to link two tables with the same value but different formats?

So I have two columns from two different databases that I would like to link.
Problem is that my first column outputs the numbers with this format "1 789 987" and my second column outputs the data "0000000001789987"
How can I write my WHERE sql forumla to idententify these as matching?
Ok so I pulled out the qrys to excel to provide you with more information.
Here are the different tables.
Looks like Tbl2 has NUM column set to text. And even though the QRY in the program gave spaces to the numbers in Tbl1 it looks like the qry removed them shrug
SELECT *
FROM "Tbl1","Tbl2"
WHERE "Tbl1"."num" = "Tbl2"."num"
AND "Tbl1"."Date" BETWEEN '2019-01-21' AND '2019-01-25'
I hope the information became abit clearer. I'm new to SQL and Stackoverflow, i'll try and improve my questions information in the future.
Well, to transform format 1 to format 2 you can try something like this :
set #format1 = "1 789 987";
set #format2 = "0000000001789987";
select LPAD(REPLACE(#format1, ' ', ''), 16, "0") as format1, #format2 as format2
Output is :
====================================
format1 | format2
====================================
0000000001789987 | 0000000001789987
This way format1 looks like format2 if you test it. The REPLACE remove the ' ' and the LPAD will fill the string with 0 untill the string is 16 char length like the format2.
So you can use this in you WHERE condition :
...WHERE LPAD(REPLACE(your_first_column, ' ', ''), 16, "0") = your_other_column
Now you can try to transform both column in int too, you didn't provide lot of information about those format so hard to find the best solution !
This cast may fit for you:
NOTE: tbl1 contains ids like: 1 789 987
select *
from tbl1 join tbl2 on (
cast( -- casts to integer
replace(tbl1.text_id, ' ', '') -- removes whitespaces
as int) =
tbl2.numeric_id -- join on second table
)
In any case please provide sample data and a testable example what you did and the results you need

Convert string to int in MySQL

I have a column with names like:
Ernest Hemingway
Jackson Pollock
I want to convert them to numbers and store them in an INT field. Maybe getting the position of each letter in the alphabet or something like this, resulting a number:
23764283456
23984623746
Is there any function to do something like this? I don't mind the length of the INT or if the result is one number or another. The important thing is that every time I apply the function to a name, the result is the same.
Thanks!
Try this:
crc32('Ernest Hemingway');
will always give you 2479642411
as #Gordon_Linoff said in the comments large number can't be store on filed of type int
but I will show you how to convert string to the ascii of the chars
you can use HEX
SELECT HEX('test')
+-------------+
| HEX('test') |
+-------------+
| 74657374 |
+-------------+
This is a one-way hash, but with an important concern: the integer should be representable on the platform.
PHP code, assuming 32-bit compatibility is desired:
$hash = sha1('Ernest Hemingway');
// last 6 characters, represent 3 bytes
$hash = substr($hash, -6);
$result = hexdec($hash); // integer: 1331016
Keep in mind this has a very low entropy: 2^24 = 16777216 possibilities
4 bytes is too large, because signed/unsigned integer discrepancies would lead to float with some inputs, and floats really can't be casted to integers with perfect determinism.
SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;

Creating an encryption in MySQL

I am trying to create a an encryption in MySQL.
Lets say there is a string of characters.
"I can run for as many".
I want to replace each letter with its fourth letter.
For example,
'a' replaced with 'e'
'b' replaced with 'f'
and so on.
The Final output of the above would look something like this.
"M gen vyr jsr ew qerc"
The best I could come up is the below.
Since it is a nested function, it is not giving me the right result.
The below function replaces 'a' with 'e' and then again replaces 'e' with 'i'
until it reaches the end.
select messagetext,
replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(messagetext,'a','e'),
'b','f'),'c','g'),'d','h'),'e','i'),'f','j'),'g','k'),
'h','l'),'i','m'),'j','n'),'k','o'),'l','p'),'m','q'),
'n','r'),'o','s'),'p','t'),'q','u'),'r','v'),'s','w'),
't','x'),'u','y'),'v','z'),'w','a'),'x','b'),'y','c'),
'z','d')
from chat;
Any help would be much appreciated.
Reached partial solution, now stuck.
Putting it here so that others can work on this.
Query:
SELECT UNHEX(HEX(val) + REPEAT('04', LENGTH(val))) AS rot4 FROM caeser;
+--------+
| rot4 |
+--------+
| efghip |
| aq?? | <-- Need to rotate / mod hex value for this. (Stuck here)
+--------+
Table create queries:
CREATE TABLE caeser (val VARCHAR(255));
INSERT INTO caeser ('abcdef');
INSERT INTO caeser VALUES ('uvwxyz');
PS: will convert to community wiki, if others also contribute.

MySQL string cast to unsigned

If I have a string that starts with a number, then contains non-numeric characters, casting this string to an integer in MySQL will cast the first part of the string, and give no indication that it ran into any problems! This is rather annoying.
For example:
SELECT CAST('123' AS UNSIGNED) AS WORKS,
CAST('123J45' AS UNSIGNED) AS SHOULDNT_WORK,
CAST('J123' AS UNSIGNED) AS DOESNT_WORK
returns:
+-------------+---------------+-------------+
| WORKS | SHOULDNT_WORK | DOESNT_WORK |
+-------------+---------------+-------------+
| 123 | 123 | 0 |
+-------------+---------------+-------------+
This doesn't make any sense to me, as clearly, 123J45 is not a number, and certainly does not equal 123. Here's my use case:
I have a field that contains (some malformed) zip codes. There may be mistypes, missing data, etc., and that's okay from my perspective. Because of another table storing Zip Codes as integers, when I join the tables, I need to cast the string Zip Codes to integers (I would have to pad with 0s if I was going the other way). However, if for some reason there's an entry that contains 6023JZ1, in no way would I want that to be interpreted as Zip Code 06023. I am much happier with 6023JZ1 getting mapped to NULL. Unfortunately, IF(CAST(zipcode AS UNSIGNED) <= 0, NULL, CAST(zipcode AS UNSIGNED)) doesn't work because of the problem discussed above.
How do I control for this?
Use a regular expression:
select (case when val rlike '[0-9][0-9][0-9][0-9][0-9]' then cast(val as unsigned)
end)
Many people consider it a nice feature that MySQL does not automatically produce an error when doing this conversion.
One options is to test for just digit characters 0 thru 9 for the entire length of the string:
zipstr REGEXP '^[0-9]+$'
Based on the result of that boolean, you could return the integer value, or a NULL.
SELECT IF(zipstr REGEXP '^[0-9]+$',zipstr+0,NULL) AS zipnum ...
(note: the addition of zero is an implicit conversion to numeric)
Another option is to do the conversion like you are doing, and cast the numeric value back to character, and compare to the original string, to return a boolean:
CAST( zipstr+0 AS CHAR) = zipstr
(note: this second approach does allow for a decimal point, e.g.
CAST( '123.4'+0 AS CHAR ) = '123.4' => 1
which may not be desirable if you are looking for just a valid integer

Search string mysql db that can have spaces, be in another string, etc

I have this database wich contains product codes like
EXA 075 11112
0423654
3 574 662 123
JOLA 22354 5
LUCS 2245 785
I use a query with %LIKE% to list the products mathing a string entered by the user for example "22" would list
JOLA 22354 5
LUCS 2245 785
The problem is that the user does not necessarily know the format of the code, so it types in 07511112 and the output is zero, because "EXA 075 11112" is not matched by %LIKE%.
Is there a way to construct the query to trim all spaces from the product field before the search occurs, and then search by the string also trimed of spaces using %LIKE% ? I guess it should then match all entries. Or is there another way ?
I cannot run replace ' ', '' on the column, the codes must remains as there are now.
You could use replace function
select *
from mytable
where REPLACE( `productcode` , ' ' , '' ) like '%searchparam%'