I'm querying a table that has a column with member_ids stuffed in a pipe delimited string. I need to return all rows where there is an 'exact' match for a specific member_id. How do I deal with other IDs in the string which might match 'part' of my ID?
I might have some rows as follows:
1|34|11|23
1011
23|1
5|1|36
64|23
If I want to return all rows with the member_id '1' (row 1, 3 and 4) is that possible without having to extract all rows and explode the column to check if any of the items in the resulting array match.
MySQL's regular expressions support a metacharacter class that matches word boundaries:
SELECT ...
FROM mytable
WHERE member_ids REGEXP '[[:<:]]1[[:>:]]'
See http://dev.mysql.com/doc/refman/5.6/en/regexp.html
If you don't like that, you can search using a simpler regular expression, but you have to escape the pipes because they have special meaning to regular expressions. And you also have to escape the escaping backslashes so you get literal backslashes through to the regular expression parser.
SELECT ...
FROM mytable
WHERE member_ids REGEXP '\\|1\\|'
You can do this in one expression if you modify your strings to include a delimiter at the start and the end of the string. Then you don't have to add special cases for beginning of string and end of string.
Note this is bound to do a table-scan. There's no way to index a regular expression match in MySQL. I agree with #MichaelBerkowski, you would be better off storing the member id's in a subordinate table, one id per row. Then you could search and sort and all sorts of other things that the pipe-delimited string makes awkward, inefficient, or impossible. See also my answer to Is storing a delimited list in a database column really that bad?
'|' has a specific meaning in REGEXP. So suppose that the ids are separated by another delimiter like '~'.
Then you can run this code:
SELECT * FROM `t1`
where (Address Regexp '^1~') or
(Address Regexp '~1$') or
(Address Regexp '^1$') or
(Address Regexp '~1~')
Related
I am trying to select all client names without vowels from a table (should therefore return an empty list) using the setminus operator with regular expressions, but it is simply returning the entire column. The same happens if I try to select all client names without 'a' or 'e' or any other vowel.
This is the query I'm using:
select client_name from client
where client_name regexp '[^aeiou]';
If I try doing a condition like below, then the inside caret actually does take every character other than 'a'. I'm not sure why it doesn't work by itself though.
select client_name from client
where client_name regexp '^[^a]'
Expected - empty output
Actual Results - whole column is returned
The regular expression can match anywhere in the name. So it will match any name that has any non-vowel character, not where all the characters are not vowels. You need to anchor it and quantify it:
WHERE client_name REGEXP '^[^aeiou]*$'
This tests all the characters in the name.
Or you can negate the test:
WHERE client_name NOT REGEXP '[aeiou]'
The regexp matches a vowel anywhere in the name. Then using NOT makes this return the names that don't match.
I have got a table in one of the columns I got data separated by comma, I've been trying to figure out how I can make a query with MySQL that checks in this column that I got a name that has comma only once:
table
SELECT Name, num FROM biology WHERE Name = 'Yossi' AND contains (', ')=1 ;
So I would get only
table2
Thanks
You an use FIND_IN_SET() to find rows where the comma separated list contains a specific word.
There is no elegant way to count the rows with exactly two elements in the comma separated list, but one way to accomplish this is to compare the length of the string with commas to the length of the string with the commas removed. If removing all commas shortens the length by 1 character that means there is exactly one comma.
Something like this should work for you:
select *
from your_table
where find_in_set('Yossi',name)
and char_length(name) = (char_length(replace(name,',','')) + 1)
I have a table, one of the columns contains a text values, some of which are comma separated string, like this:
Downtown, Market District, Warehouse District
I need to modify my query to see is a given value matches this column. I decided that using IN() is the best choice.
SELECT *
FROM t1
WHERE myValue IN (t1.nighborhood)
I am getting spotty results - sometimes I return records and sometimes not. If there's a value in t1.nighborhood that matches myValue, I do get data.
I checked and there are no MySQL errors. What am I missing?
You can use FIND_IN_SET() to search a comma-delimited list:
SELECT *
FROM t1
WHERE FIND_IN_SET(myValue, REPLACE(t1.nighborhood, ', ', ','));
The REPLACE() is necessary to remove the extra spaces.
Another solution is to use regex to match your search value surrounded by commas if necessary:
SELECT *
FROM t1
WHERE t1.nighborhood REGEXP CONCAT('(^|, )', myValue, '(, |$)');
In general, it's bad design to store distinct values in a single column. The data should be normalized into a related table with a foreign key.
I need a SELECT query in MYSQL that will retrieve all rows in one table witch field values contain "?" char with one condition: the char is not the last character
Example:
ID Field
1 123??see
2 12?
3 45??78??
Returning rows would then be those from ID 1 and 3 that match the condition given
The only statement I have is:
SELECT *
FROM table
WHERE Field LIKE '%?%'
But, the MySQL query does not solve my problem..
The LIKE expressions also support a wildcard "_" which matches exactly one character.
So you can write an expression like the example below, and know that your "?" will not be the last character in the string. There must be at least one more character.
WHERE intrebare LIKE '%?_%'
Re comment from #JohnRuddell,
Yes, that's true, this will match the string "??" because a "?" exists in a position that is not the last character.
It depends whether the OP means for that to be a match or not. The OP says the string "45??78??" is a match, but it's not clear if they would intend that "4578??" to be a match.
An alternative is to use a regular expression, but this is a little more tricky because you have to escape a literal "?", so it won't be interpreted as a regexp metacharacter. Then also escape the escape character.
WHERE intrebare REGEXP '\\?[^?]'
you can just add an additional where where the last character is not a ?
SELECT *
FROM intrebari
WHERE intrebare LIKE '%?%' AND intrebare NOT LIKE '%?'
you could also do it like this
SELECT *
FROM intrebari
WHERE intrebare LIKE '%?%' AND RIGHT(intrebare,1) <> '?'
DEMO
I have a simple task where I need to search a record starting with string characters and a single digit after them. What I'm trying is this
SELECT trecord FROM `tbl` WHERE (trecord LIKE 'ALA[d]%')
And
SELECT trecord FROM `tbl` WHERE (trecord LIKE 'ALA[0-9]%')
But both of the queries always return a null record
trecord
-------
null
Where as if I execute the following query
SELECT trecord FROM `tbl` WHERE (trecord LIKE 'ALA%')
it returns
trecord
-------
ALA0000
ALA0001
ALA0002
It means that I have records that starts with ALA and a digit after it,
EDIT
I'm doing it using PHP MySQL and innodb engine to be specific.
I think you can use REGEXP instead of LIKE
SELECT trecord FROM `tbl` WHERE (trecord REGEXP '^ALA[0-9]')
In my case (Oracle), it's WHERE REGEXP_LIKE(column, 'regex.*'). See here:
SQL Function
Description
REGEXP_LIKE
This function searches a character column for a pattern. Use this
function in the WHERE clause of a query to return rows matching the
regular expression you specify.
...
REGEXP_REPLACE
This function searches for a pattern in a character column and
replaces each occurrence of that pattern with the pattern you specify.
...
REGEXP_INSTR
This function searches a string for a given occurrence of a regular
expression pattern. You specify which occurrence you want to find and
the start position to search from. This function returns an integer
indicating the position in the string where the match is found.
...
REGEXP_SUBSTR
This function returns the actual substring matching the regular
expression pattern you specify.
(Of course, REGEXP_LIKE only matches queries containing the search string, so if you want a complete match, you'll have to use '^$' for a beginning (^) and end ($) match, e.g.: '^regex.*$'.)