Rightmost occurrence string match in MySQL - mysql

I would like to extract the file extension from a field in MySQL that contains filenames. This means I need to find the final '.' character in the field and extract everything after that. The following code example partially works:
SELECT LCASE(RIGHT(filename, LENGTH(filename) - LOCATE('.', filename)))
FROM mytable;
except that it falls down for cases where the file name contains more than one '.', where it extracts too much. In most programming languages I'd expect to find a function that gives me a rightmost match, but I can't find any such thing for MySQL, nor can I find any discussion from people who have had the same problem and found a workaround.

There is the substring_index function - it does exactly what you are looking for:
SELECT substring_index(filename, '.', -1) FROM mytable

Edit:
See Martin's answer, using substring_index(), with a negative count parameter is a MUCH better approach!
I'm downvoting myself (actually that's not possible...), upvoting Martin's answer; ' wish I could pass the accepted answer to him... Maybe OP will do that.
Original answer:
The following may do the trick (ATN: length may be off by 1, also may want to deal with case of filename value without a dot character.
SELECT LCASE(RIGHT(filename, LOCATE('.', REVERSE(filename) ) ))
FROM mytable;
Beware however that this type of post-facto parsing can be quite expensive (read slow), and you may consider extracting the file extension to a separate column, at load time.

Related

sql split issue from a string having more than 2 '-', and i have to fetch all data whatever their is present after 2'-'

i have to fetch model no. col data from ivm col. data.
ivm
model no
534643-240-0671258
0671258
2894262-101107-V5009-L
V5009-L
732189-149-NV51K6650SS
NV51K6650SS
1139081-97531-PB1100PS1
PB1100PS1
89234-79794-T10358-4-CP
T10358-4-CP
2591217-104703-AGAKN95
AGAKN95
793509-81227-79246-RB
79246-RB
On BigQuery we can try using REGEXP_EXTRACT:
SELECT ivm, REGEXP_EXTRACT(ivm, r'(?:[^-]+-){2}(.*)') AS model_no
FROM yourTable;
Here is an explanation of the regex pattern used:
(?:[^-]+-){2} match ABC123-DEF456- (i.e. first 2 terms)
(.*) then capture everything else which follows
Consider below approach (BigQuery) - I think in this option regexp is much easier to swallow :o) - it just looks for two groups of digits at the beginning and simply removes them - leaving exactly what you are looking for - which is the rest of string
select ivm, regexp_replace(ivm, r'^\d+-\d+-', '') as model_no
from your_table
if applied to sample data in your question - output is

Regex to find exact match in a string works elsewhere but not on MySql Query

The given string is a comma separated value, for example the string below
29,30,31,32,33,34,35,36,192,225,228,233,239,240,144,145
I want to find the exact whole match of any number in the string, and I did write a regex to find it. When I checked it on regex101, it worked well. But when I wrote the same regex on MySql Query, it did not work
(SELECT * FROM table_name WHERE (value REGEXP '.*\b22\b,{0,1}.*')
I did find another query that works, it used concat() function.
SELECT * FROM table_name WHERE CONCAT(',',value,',') like '%,22,%'
Edit: The answer from #anubhava also works (which can be found on the very first comment on this question). Since I am able to pick only one answer as Solved, I just wanted to let others know.
Thanks again
On your version of MySQL, most likely word boundaries are denoted by [[:<:]] and [[:>:]]:
SELECT *
FROM table_name
WHERE value REGEXP '[[:<:]]22[[:>:]]';
I believe that starting with MySQL 8+, it is possible to use the more standard \b to represent a word boundary. Check the demo link below to see it working on MySQL 5.7.
Demo
There is a function just for this task:
WHERE FIND_IN_SET('22', '29,30,31,32,33,34,35,36,192,225,228,233,239,240,144,145')

SQL query to select strings that contain a "Unit Separator" character

I have table like this
I want get those record which content Unit Separator
I have try many things but not getting result.I try with char(31) and 0x1f and many other ways but not getting desired result.This is my query which i try
SELECT * FROM `submissions_answers` WHERE `question_id`=90 AND `answer` like '%0x1f%'
How can i do this? Please help me..
Problem
The expression you tried won't work because answer LIKE '%0x1f%' is looking for a string with literally '0x1f' as part of it - it doesn't get converted to an ASCII code.
Solutions
Some alternatives to this part of the expression that ought to work are:-
answer LIKE CONCAT('%', 0x1F, '%')
answer REGEXP 0x1F
INSTR(answer, 0x1F) > 0
Further consideration
If none of these work then there may be a further possibility. Are you sure the character seen in the strings is actually 0x1F? I only ask because the first thing I tried was to paste in ␟ but it turns out MySQL see this as a decimal character code of 226 rather than 31. Not sure which client you are using but if the 0x1F character is in the string, it might not actually appear in the output.
Demo
Some tests demonstrating the points above: SQL Fiddle demo
You can use:
SELECT * FROM submissions_answers WHERE question_id=90 AND instr(answer,char(31))>0
The keyword here being the INSTR MySQL function, which you can read about here. This function returns the position of the first occurrence of substring (char(31)) in the string (answer).
Yet another way...
SELECT * FROM `submissions_answers`
WHERE `question_id`=90
AND HEX(`answer`) REGEXP '^(..)*1F'
Explanation of the regexp:
^ - start matching at the beginning (of answer)
(..)* -- match any number (*) of 2-byte things (..)
then match 1F, the hex for US.
You could convert the answer column into a HEX value, and then look for values containing that hex string.
SELECT * FROM `submissions_answers`
WHERE HEX(`answer`) LIKE '%E2909F%'

MySQL Find similar strings

I have an InnoDB database table of 12 character codes which often need to be entered by a user.
Occasionally, a user will enter the code incorrectly (for example typing a lower case L instead of a 1 etc).
I'm trying to write a query that will find similar codes to the one they have entered but using LIKE '%code%' gives me way too many results, many of which contain only one matching character.
Is there a way to perform a more detailed check?
Edit - Case sensitive not required.
Any advice appreciated.
Thanks.
Have a look at soundex. Commonly misspelled strings have the same soundex code, so you can query for:
where soundex(Code) like soundex(UserInput)
use without wildcard % for that
SELECT `code` FROM table where code LIKE 'user_input'
thi wil also check the space
SELECT 'a' = 'a ', return 1 whereas SELCET 'a' LIKE 'a ' return 0
reference

MYSQL:Looking for equivalent of Perl's "regex" =~ s/e/i/g => rigix in a MySQL Select

Can I match and replace a text pattern in a MYSQL select?
EDIT
For now it looks like the answer is: Can't be done,
since you can't capture what was matched (from Eric's answer / comments). For now I will look into adding a lookup table.
Simplified example:
The MySQL table Coleridge holds many strings like:
text
------------------------------------
In_Xanadu_did_Kubla_Khan
A_stately_pleasure_dome_decree
Where_Alph_the_sacred_river_ran
Through_caverns_measureless_to_man
Down_to_a_sunless_sea
Is there a way to express the select
SELECT text =~ s / [ ^_ ] + _ ( .* ) _ [ ^_ ] + $ / \1 / as replaced FROM Coleridge
and get
replaced
________________________
Xanadu_did_Kubla
stately_pleasure_dome
Alph_the_sacred_river
caverns_measureless_to
to_a_s
Please Note:
The regular expression s/ / / I
provided is much less complicated
than what the real world DB contains
Unfortunately I can't normalize
the DB ..
There's no regex way to replace anything in MySQL. You can match in MySQL based on RegEx (regexp), but that doesn't return what part is matched, just the whole column that is. But, you can use replace like so:
select replace(col, 'e', 'i') from tbl
This will return regex as rigix.
As for your specific example, you'd have to use a combination of locate and substring:
select
substring(col
, locate('_', col)+1
, locate('_', reverse(col))-(len(col)-locate('_', col)-1))
from tbl
The general rule on string manipulations/handling on the database level is: Keep it simple. RDBMS's think in sets, and that's where they shine. Pulling individual string manipulations is not in their sweet spot. As such, no RDBMS has really mature string handling functions (and there certainly isn't any consistency across the different ones). If your regex is reasonably complex, you will most likely want to just handle it on the presentation/app layer, and not in the database.
No, you can't. MySQL only supports regexes for matching (RLIKE), not replacement.