RegEx in select from table in db - mysql

Problem:
I have a table like this :
A | B
-----------------------------------------
1 | 5,25,24,22,21,6,19,18,17,15,13,11
2 | 25,15,17,4,33,12,34,40,24,5,1,26,43,9
3 | 25,15,11,36,29
I need to select rows where my number is in column B.
try:
I use RegEx for this. I write this code :
SELECT *
FROM `table`
WHERE `B` REGEXP "([^\d]|^)MYNUMBER[^\d]
and RLIKE
([^\d]|^)MYNUMBER[^\d] :
([^\d]|^) : not number or be a first char.
MYNUMBER
[^\d] : not number
When MYNUMBER is 25 or 34 or any double digit number, I haven't got any problem.
But when MYNUMBER is 5 or 1 or any one digit number, it's trouble.
Result example1:
input: MYNUMBER : 24
result:
A | B
-----------------------------------------
1 | 5,25,24,22,21,6,19,18,17,15,13,11
It's okay.
Result example2:
input: MYNUMBER : 5
result:
A | B
-----------------------------------------
1 | 5,25,24,22,21,6,19,18,17,15,13,11
2 | 25,15,17,4,33,12,34,40,24,5,1,26,43,9
3 | 25,15,11,36,29
Wrong answer, row 3 is wrong.
It is strange:
I tried my expression in regexr.com and it's true.

MySQL has a function for this: FIND_IN_SET()
http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_find-in-set
In the long run you may want to think about normalizing this into two tables ...

The number has to be a consecutive set of digits that is either surrounded by commas, or is the first or last thing in the string. You could add to this to tolerate optional whitespace if desired.
SELECT *
FROM `table`
WHERE `B` REGEXP "^25," OR `B` REGEXP ",25," OR `B` REGEXP ",25$"

Related

Select integer column as corresponding letter of the alphabet

I have an int column that contains values no larger than about 20. I want to select as its corresponding upper case letter of the alphabet:
1 = A
2 = B
3 = C
...
I don't care what happens after Z because the column doesn't contain larger values. Is there a simple way to do this with a SQL query, to convert to a single-byte character like this?
Add 64 to your integer and you have the ASCII value of the letter you want.
mysql> select CHAR(1+64);
+------------+
| CHAR(1+64) |
+------------+
| A |
+------------+
Read https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char
Another alternative specific to MySQL using elt
select elt(col,'A','B','C','D','E','F',...);
Demo

contains function for String in presto Athena

I have a table with ORC Serde in Athena. The table contains a string column named greeting_message. It can contain null values as well. I want to find how many rows in the table have a particular text as the pattern.
Let's say my sample data looks like below:
|greeting_message |
|-----------------|
|hello world |
|What's up |
| |
|hello Sam |
| |
|hello Ram |
|good morning, hello |
| |
|the above row has null |
| Good morning Sir |
Now for the above table, if we see there are a total of 10 rows. 7 of them are having not null values and 3 of them just has null/empty value.
I want to know what percentage of rows contain a specific word.
For example, consider the word hello. It is present in 4 rows, so the percentage of such rows is 4/10 which is 40 %.
Another example: the word morning is present in 2 messages. So the percentage of such rows is 2/10 which is 20 %.
Note that I am considering null also in the count of the denominator.
SELECT SUM(greeting_message LIKE '%hello%') / COUNT(*) AS hello_percentage,
SUM(greeting_message LIKE '%morning%') / COUNT(*) AS morning_percentage
FROM tablename
The syntax of prestoDB (Amazon Athena engine) is different than MySQL. The following example is creating a temp table WITH greetings AS and then SELECT from that table:
WITH greetings AS
(SELECT 'hello world' as greeting_message UNION ALL
SELECT 'Whats up' UNION ALL
SELECT '' UNION ALL
SELECT 'hello Sam' UNION ALL
SELECT '' UNION ALL
SELECT 'hello Ram' UNION ALL
SELECT 'good morning, hello' UNION ALL
SELECT '' UNION ALL
SELECT 'the above row has null' UNION ALL
SELECT 'Good morning Sir')
SELECT count_if(regexp_like(greeting_message, '.*hello.*')) / cast(COUNT(1) as real) AS hello_percentage,
count_if(regexp_like(greeting_message, '.*morning.*')) / cast(COUNT(1) as real) AS morning_percentage
FROM greetings
will give the following results
hello_percentage
morning_percentage
0.4
0.2
The regex_like function can support many regex options including spaces (\s) and other string matching requirements.

Find the last 5 digits even when there is a character and convert them to integer

I have to always get the last 5 digits from a string and need to convert it to int.
But I have situations where the 5th digit from the end is a character.
If I have the a character then I want to just get the number.
Sample data:
Input Expected Output
978568-16258 16258
ERGF99252697 52697
SP-988824-189241 89241
SP-456790-568723 68723
SP-456790-568 568
I'have tried some thing like this:
select CAST((RIGHT(RTRIM(col_1),5)) AS UNSIGNED INT) as test from table_A;
For few of the reults its ok but when it sees characters then it displays a random number.
How can I resolve this issue?
If you are running MySQL 8.0 / MariaDB 10.0.5, you can use regexp_substr() for this. This should be as simple as:
select cast(regexp_substr(col_1, '[0-9]{1,5}$') as unsigned) from table_A
Regexp '[0-9]{1,5}$' means: as many digits as possible (maximum 5) at the end of the string.
Demo on DB Fiddle:
col_1 | col_1_new
:--------------- | :--------
978568-16258 | 16258
ERGF99252697 | 52697
SP-988824-189241 | 89241
SP-456790-568723 | 68723
SP-456790-568 | 568
For older versions of MySQL/MariaDB, you can do:
select cast(right(col_1,
(col_1 regexp "[0-9]{1}$") +
(col_1 regexp "[0-9]{2}$") +
(col_1 regexp "[0-9]{3}$") +
(col_1 regexp "[0-9]{4}$") +
(col_1 regexp "[0-9]{5}$")
) as unsigned) from table_A;

SQL query to select columns with exact like?

Consider this SQL table
id | name | numbers
------------------------
1 | bob | 1 3 5
2 | joe | 7 2 15
This query returns the whole table as its result:
SELECT * FROM table WHERE numbers LIKE '%5%'
Is there an SQL operator so that it only returns row 1 (only columns with the number 5)?
Use regexp with word boundaries. (But you should ideally follow Gordon's comment)
where numbers REGEXP '[[:<:]]5[[:>:]]'
It's a pity that you are not using the comma as a separator in your numbers column, because it would be possible to use the FIND_IN_SET function, but you can use it together with REPLACE, like this:
SELECT * FROM table WHERE FIND_IN_SET(5, REPLACE(numbers, ' ', ','));

mySQL SELECT IN from string

Here is my table X:
id vals
---------------------
1 4|6|8|
Now table Y:
id name
--------------------
1 a
4 b
6 c
8 d
Now I want the following:
select * from Y where id IN (replace(select vals from X where id = '1'),'|',',')
But this does not seem to work. Any ideas why?
You may use FIND_IN_SET instead of just IN, normal IN keyword couldn't search between comma seperated values within one field.
For example
mysql> select FIND_IN_SET(4, replace('4|6|8|','|',','));
+-------------------------------------------+
| FIND_IN_SET(4, replace('4|6|8|','|',',')) |
+-------------------------------------------+
| 1 |
+-------------------------------------------+
1 row in set (0.00 sec)
Replace gives you a string back - but it's a string value, not a string as in part of your query.
What you can do is instead of using IN, use a REGEXP to match within your original string, for example:
vals REGEXP '[[:<:]]4[[:>:]]'
would be true only if there is a "4" in the original string that isn't part of a larger number (thus if you have 3|44|100 it wouldn't match on "4" but would match on "44").
The [[:<:]] and [[:>:]] are "left side of word" and "right side of word" respectively.
To generate that string, you can do something like...
CONCAT('[[:<:]]', CAST(id AS CHAR), '[[:>:]]')