mySQL SELECT IN from string - mysql

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), '[[:>:]]')

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

MySQL - REGEX Search word from string and matched word should be either alnum or numeric only

Question: If i pass any word in where clause then query should return only if passing word is alnum or num only using mysql regex.
I have a table where addresses.
address table
--------------------
id | name
--------------------
1 | 123 demo
--------------------
2 | 1st demo
--------------------
3 | 123
--------------------
4 | demo
Example 1
SELECT * FROM address WHERE name regexp '(^|[[:space:]])123([[:space:]]|$)'
Result: Row 1,3 should return. it works for me
Example 2
SELECT * FROM address WHERE name regexp '(^|[[:space:]])1st([[:space:]]|$)'
Result: Row 2 should return. it works for me
Example 3
SELECT * FROM address WHERE name regexp '(^|[[:space:]])demo([[:space:]]|$)'
Result: It should not return any row. but it return 1,2,4 row
Final : So if i pass "demo" in where clause then no result should return.
http://sqlfiddle.com/#!9/acc5c8/2
I want to recommend wordboundary syntax like this: REGEXP '[[:<:]]demo[[:>:]]'
http://sqlfiddle.com/#!9/d63e05/1
Honestly, if this were my project, I'd be doing a ctype_alnum() check on the search value before bothering to make a trip to the database. However, your requirement is:
only if passing word is alnum or num only using mysql regex
To ensure that the needle string in the query contains at least one number, add another check to the WHERE clause.
More specifically...
SELECT * FROM address WHERE address REGEXP '[[:<:]]demo[[:>:]]' AND 'demo' REGEXP '[0-9]'
This will return no rows as desired.

MYSQL Checking even/odd within a substring

I have a query where one condition to check if a room number is odd/even. The issue is that the room number is stored with the building info as well in a string.
Here is the format of the data in the database:
ABC-0101A (Odd)
ABC-0112B (Even)
ZYX-123A1 (Odd)
ZYX-456B1 (Even)
For a room number to be considered even/odd, it is dependent on the last number before the first letter after the dash.
This would be quite a lot easier and more performant if you could separately store the numeric portion in another column. As a long term solution, I would recommend doing that.
But you can use a regular expression here to match the last digit before the first number, with a set of even [02468] and a set of odd [13579] with a CASE statement.
SELECT
CASE
WHEN room REGEXP '-[0-9]*[02468][A-Z]' THEN 'even'
WHEN room REGEXP '-[0-9]*[13579][A-Z]' THEN 'odd'
ELSE 'something else entirely'
END
FROM rooms
The pattern -[0-9]* matches a literal hyphen followed by zero or more digits. Then the significant part is the [02468] or [13579] set to match an even or odd digit that must be present immediately preceding [A-Z] matching the next letter.
Here's a demonstration: http://sqlfiddle.com/#!9/464d1d/3
Exmaple matching an even room:
SELECT 'ABC-0112B' REGEXP '-[0-9]*[02468][A-Z]';
+------------------------------------------+
| 'ABC-0112B' REGEXP '-[0-9]*[02468][A-Z]' |
+------------------------------------------+
| 1 |
+------------------------------------------+
Example matching an odd room:
SELECT 'ABC-0101A' REGEXP '-[0-9]*[13579][A-Z]';
+------------------------------------------+
| 'ABC-0101A' REGEXP '-[0-9]*[13579][A-Z]' |
+------------------------------------------+
| 1 |
+------------------------------------------+
Example matching an odd room that doesn't end with a letter:
SELECT 'ABC-0101A11' REGEXP '-[0-9]*[13579][A-Z]';
+--------------------------------------------+
| 'ABC-0101A11' REGEXP '-[0-9]*[13579][A-Z]' |
+--------------------------------------------+
| 1 |
+--------------------------------------------+
First create a function IsNumeric which returns 1 if number is integer otherwise 0:
CREATE FUNCTION IsNumeric (input varchar(1024)) RETURNS int
RETURN input REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
Then use following query to check room number:
select IF (IsNumeric(right(room,1))>0,
IF(right(room,1)%2=0,'Even','ODD'),
IF(left(right(room,2),1)%2=0,'Even','ODD')
) as room_number
from rooms;
Here in above query first check if last digit is integer, If so then check for even/Odd number. If digit is not integer pick the 2nd last digit and apply the same check.

RegEx in select from table in db

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$"

"Where" statement: match a single word (not substring)

I am using MySQL.
I have a car table in my database, and there is a name column in that table.
Suppose the name column of the table contain values:
+----------+
| name |
+----------+
| AAA BB |
----------
| CC D BB |
----------
| OO kk BB |
----------
| PP B CC |
----------
I would like to search the table where name column value contains word "BB" (not substring), What is the SQL command to achieve this ?
I know LIKE , but it is used to match a contained substring, not for a word match.
P.S.
My table contains large data. So, I probably need a more efficient way than using LIKE
The values in name column are random strings.
Please do not ask me to use IN (...) , because the values in that column is unpredictable.
Try this WHERE clause:
WHERE name LIKE '% BB %'
OR name LIKE 'BB %'
OR name LIKE '% BB'
OR name = 'BB'
Note that this will not perform well if your table is large. You may also want to consider a full-text search if you need better performance.
You can use the REGEXP operator in MySQL:
SELECT *
FROM car
WHERE name REGEXP '[[:<:]]BB[[:>:]]'
It will match BB if it occurs as a single word. From the MySQL manual:
[[:<:]], [[:>:]]
These markers stand for word boundaries. They match the beginning and end of words, respectively. A word is a sequence of word characters that is not preceded by or followed by word characters. A word character is an alphanumeric character in the alnum class or an underscore (_).
mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1
mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0