I have a table containing following values :
id | value |
-----------------------
1 | 1,2,5,8,12,20 |
2 | 11,25,26,28 |
-----------------------
now I want to search some comma separated IDs e.g. '1,3,6,7,11' from above value column e.g.
SELECT id FROM tbl_name
WHERE value REGEXP '*some reg exp goes here containing 1,3,6,7,11*'
LIMIT 1,0;
SELECT id FROM tbl_name
WHERE value REGEXP '*some reg exp goes here containing 3,6,27,15*'
LIMIT 1,0;
above 1st query should return 1 while the 2nd should return NULL
I am new with regular expressions can anyone help. Thanks
REGEXP '(^|,)(1|3|6|7|11)(,|$)'
Will match all values containing one number of the sequence 1,3,6,7,11.
You should not use one column to save several values. Normalize data!
Edited answer
Related
I have something like in table
mysql> select uuid , short-uuid FROM sampleUUID WHERE identifier ="test123";
+--------------------------------------+-------------+
| uuid | short-uuid |
+--------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848 | 8033863ee848 |
| 22b6f783-aeaf-1195-97ef-a6d8c47261b1 | 8033863ee848 |
| 33c51085-ccd8-1119-ac37-332510a16e1b | 332510a16e1b |
+--------------------------------------+-------------+
I would be needing a result like (grouped all in single row, single value w.r.t uuid and short-uuid being same)
| uuidDetails
+----------------------------------------------------------------------------------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848,22b6f783-aeaf-1195-97ef-a6d8c47261b1|8033863ee848&&33c51085-ccd8-1119-ac37-332510a16e1b| 332510a16e1b |
+----------------------------------------------------------------------------------------------------------------+-------------+
(basically grouping uuid and short uuid in a single row from multiple rows and columns)
I know this can be achieved by select GROUP_CONCAT(uuid)FROM sampleUUID WHERE identifier ="test123" group by short-uuid;
but i don't wanna use group by here because that give multiple rows, i would need all in one row .
I have tried with below stuffs but failed to get the the results in single row
select ANY_VALUE(CONCAT_WS( '||',CONCAT_WS('|',GROUP_CONCAT(uuid) SEPARATOR ','),short-uuid)) )as uuidDetails from sampleUUID
where identifier ="test123";
this resulted like below with not appending short-uuid properly (there is only 1 short uuid appended here,Actually it needs to be grouped first 2 uuids with 1 short(because same short-uuid) uuid and 3rd uuid with other short uuid)
| uuidDetails
+----------------------------------------------------------------------------------------------------------------+-------------+
| 11d52ebd-1404-115d-903e-8033863ee848,22b6f783-aeaf-1195-97ef-a6d8c47261b1,33c51085-ccd8-1119-ac37-332510a16e1b| 332510a16e1b |
+----------------------------------------------------------------------------------------------------------------+-------------+
which is not i expected
Any help here will be appreciated . Thank you
Use nested queries.
SELECT GROUP_CONCAT(result ORDER BY result SEPARATOR '&&') AS uuidDetails
FROM (
SELECT CONCAT(GROUP_CONCAT(uuid ORDER BY uuid SEPARATOR ','), '|', short_uid) AS result
FROM sampleUUID
WHERE identifier = 'test123'
GROUP BY short_uid
) AS x
NOTE: If there is no requirement for ordering of the UUID values, we can use ORDER BY inside the GROUP_CONCAT aggregates to make the result more deterministic, so the query will return just one of a number of possible results given the same data e.g. return aa,bb|1&&cc|3 rather than bb,aa|1&&cc|3 or cc|3&&aa,bb|1 or cc|3&&bb,aa|1.
I have a MySQL database with a varchar column (although the column type can be changed if needed).
The column stores some ids separated with underscores like so:
Row 1: 1
Row 2: 1_2_3
Row 3: 10_2
Row 4: 4_5_1
Is there anyway in this structure to query that column for 1 and return all rows with 1 (but not Row 3 which contains 1 but the ID is 10).
To get the current results I am attempting to search the column LIKE %1%.
Or do I need to change the structure to achieve the result I want?
Maybe you can try:
select *
from t
where c like '1\_%'
or c like '%\_1'
or c like '%\_1\_%'
or c = '1'
You need to escape the underscore as \_, since SQL defines it as a wildcard and will match any character.
If we had a comma separator, then we could use MySQL FIND_IN_SET function.
We can use MySQL REPLACE function to change the underscores to commas,
e.g.
SELECT t.*
FROM t
WHERE FIND_IN_SET('1',REPLACE( t.id ,'_',','))
Reference:
https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_find-in-set
https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace
NOTE:
Storing underscore separated lists is an antipattern. See Chapter 2 of Bill Karwin's book "SQL Antipatterns: Avoiding the Pitfalls of Database Programming"
https://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557
With the operator like:
select * from tablename
where concat('_', id, '_') like '%#_1#_%' escape '#'
See the demo.
Results:
| id |
| ----- |
| 1 |
| 1_2_3 |
| 4_5_1 |
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.
I have a user table containing a column(say interests) with comma separated interest ids as a value.
e.g.
user interests
A 12,13,15
B 10,11,12,15
C 9,13
D 10,12
Now, I have a string with comma separated values as "13,15".
I want to fetch the users who has the interest 13,15 from above table means it should return the user A, B & C as user A contains both interest(13,15), user B matched the interest with 15 & user matched the interest with 13.
what will be the SQL as I have a lots of users in my table.
It can be done with regexp as #1000111 said, but with more complicated regexp. Look at this, for example:
(^|,)(13|15)(,|$)
This will not match 13 from 135, or 1 from 13 and so on. For example, for number 13 this will match next strings:
1,13,2
13,1,2
1,13
13,2
13
But will not match these
1,135,2
131,2
1,113
And this is query:
SET #search = '13,15';
SELECT *
FROM test
WHERE interests REGEXP CONCAT('(^|,)(', REPLACE(#search, ',', '|'), ')(,|$)')
If you want to get the result based on loose matching then you can follow this query:
Loose matching means interests like 135,151 would also appear while searching for '13,15'.
SET #inputInterest := "13,15";
SELECT
*
FROM userinterests
WHERE interests REGEXP REPLACE(#inputInterest,',','|');
For the given data you will get an output like below:
| ID | user | interests |
|----|------|-------------|
| 1 | A | 12,13,15 |
| 2 | B | 10,11,12,15 |
| 3 | C | 9,13 |
SQL FIDDLE DEMO
EDIT:
If you want result based on having at least one of the interests exactly then you can use regex as #Andrew mentioned in this answer:
Here's I've modified my query based on his insight:
SET #inputInterest := "13,15";
SELECT
*
FROM userinterests
WHERE interests REGEXP CONCAT('(^|,)(', REPLACE(#inputInterest, ',', '|'), ')(,|$)')
SEE DEMO OF IT
Note:
You need to replace the #inputInterest variable by your input string.
Suggestion:
Is storing a delimited list in a database column really that bad?
searched around awhile for a solution to this problem, but no answer yet.
Have a column of alphanumeric model ID numbers to populate an index in a certain order. Two different attempts with the order they produced:
ORDER BY Model_ID ASC
1278-8
211E
350-50
996
3800P
AP23
AP263
AP26M
JA042
ORDER BY CAST(Model_ID AS UNSIGNED), Model_ID
AP23
AP263
AP26M
JA042
211E
350-50
996
1278-8
3800P
However, I need to have it sorted like so, with all of the integer-starting numbers exhausted first:
211E
350-50
996
1278-8
3800P
AP23
AP263
AP26M
JA042
Help? Thanks
For the sample data, this will get the desired order:
ORDER BY Model_ID+0=0, Model_ID+0, Model_ID ASC
Let's unpack that a bit.
The expression Model_ID+0 evaluates Model_ID in a numeric context, by adding zero to it. Basically, MySQL gets whatever leading characters that can be converted to a number, and disregards the rest. For values that can't be interpreted as a number, MySQL returns 0.
The first expression checks if the numeric value is zero, so those will be sorted last. (MySQL returns numeric value of 1 for boolean TRUE, 0 for FALSE.)
The second expression gets the non-zero values sorted in numeric order.
NOTE: these expressions "work" for the sample data; the edge case is values that have leading zeros as the numeric value, e.g. '000ABC' will be sorted after all the other "numeric" values. And MySQL doesn't stop at just the integer portion, if there's a dot character, that can be interpreted as a decimal point.
You can see the values of the expressions (for testing), by including them in the SELECT list, e.g.
SELECT Model_ID+0=0, Model_ID+0, ...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (model_id VARCHAR(20) NOT NULL PRIMARY KEY);
INSERT INTO my_table VALUES
('1278-8'),
('211E'),
('350-50'),
('996'),
('3800P'),
('AP23'),
('AP263'),
('AP26M'),
('JA042');
SELECT model_id FROM my_table ORDER BY model_id + 0 = 0,model_id + 0;
+----------+
| model_id |
+----------+
| 211E |
| 350-50 |
| 996 |
| 1278-8 |
| 3800P |
| AP23 |
| AP263 |
| AP26M |
| JA042 |
+----------+