I have a column that has comma separated data:
1,2,3
3,2,1
4,5,6
5,5,5
I'm trying to run a search that would query each value of the CSV string individually.
0<first<5 and 1<second<3 and 2<third<4
I get that I could return all queries and split it myself and compare it myself. I'm curious if there is a way to do this so MySQL does that processing work.
Thanks!
Use
substring_index(`column`,',',1) ==> first value
substring_index(substring_index(`column`,',',-2),',',1)=> second value
substring_index(substring_index(`column`,',',-1),',',1)=> third value
in your where clause.
SELECT * FROM `table`
WHERE
substring_index(`column`,',',1)<0
AND
substring_index(`column`,',',1)>5
It seems to work:
substring_index ( substring_index ( context,',',1 ), ',', -1)
substring_index ( substring_index ( context,',',2 ), ',', -1)
substring_index ( substring_index ( context,',',3 ), ',', -1)
substring_index ( substring_index ( context,',',4 ), ',', -1)
it means 1st value, 2nd, 3rd, etc.
Explanation:
The inner substring_index returns the first n values that are comma separated. So if your original string is "34,7,23,89", substring_index( context,',', 3) returns "34,7,23".
The outer substring_index takes the value returned by the inner substring_index and the -1 allows you to take the last value. So you get "23" from the "34,7,23".
Instead of -1 if you specify -2, you'll get "7,23", because it took the last two values.
Example:
select * from MyTable where substring_index(substring_index(prices,',',1),',',-1)=3382;
Here, prices is the name of a column in MyTable.
Usually substring_index does what you want:
mysql> select substring_index("foo#gmail.com","#",-1);
+-----------------------------------------+
| substring_index("foo#gmail.com","#",-1) |
+-----------------------------------------+
| gmail.com |
+-----------------------------------------+
1 row in set (0.00 sec)
You may get what you want by using the MySQL REGEXP or LIKE.
See the MySQL Docs on Pattern Matching
As an addendum to this, I've strings of the form:
Some words 303
where I'd like to split off the numerical part from the tail of the string.
This seems to point to a possible solution:
http://lists.mysql.com/mysql/222421
The problem however, is that you only get the answer "yes, it matches", and not the start index of the regexp match.
Here is another variant I posted on related question. The REGEX check to see if you are out of bounds is useful, so for a table column you would put it in the where clause.
SET #Array = 'one,two,three,four';
SET #ArrayIndex = 2;
SELECT CASE
WHEN #Array REGEXP CONCAT('((,).*){',#ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(#Array,',',#ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
SUBSTRING_INDEX(string, delim, n) returns the first n
SUBSTRING_INDEX(string, delim, -1) returns the last only
REGEXP '((delim).*){n}' checks if there are n delimiters (i.e. you are in bounds)
Building on #Oleksiy's answer, here is one that can work with strings of variable segment lengths (within reasonable limits), for example comma-separated addresses:
SELECT substring_index ( substring_index ( address,',',1 ), ',', -1) AS address_line_1,
IF(address_parts > 1, substring_index ( substring_index ( address,',',2 ), ',', -1), '') AS address_line_2,
IF(address_parts > 2, substring_index ( substring_index ( address,',',3 ), ',', -1), '') AS address_line_3,
IF(address_parts > 3, substring_index ( substring_index ( address,',',4 ), ',', -1), '') AS address_line_4,
IF(address_parts > 4, substring_index ( substring_index ( address,',',5 ), ',', -1), '') AS address_line_5
FROM (
SELECT address, LENGTH(address) - LENGTH(REPLACE(address, ',', '')) AS address_parts
FROM mytable
) AS addresses
It's working..
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table_name group by new_col;
Related
I would need to get value from given regexp.
For example:
> :"postalCode";s:4:"3150";
Is there any way I can extract 3150, from this part of column value. Column value stored serialized objects, so postalCode variable can be null type, that way I should check if positive integer follows ;s:POSITIVE_INT:"postalCodeValue
Use SUBSTRING_INDEX:
SELECT
SUBSTRING(SUBSTRING_INDEX(col, '"', -2), 1,
INSTR(SUBSTRING_INDEX(col, '"', -2), '"') - 1) AS num
FROM yourTable;
This query will extract the last quoted number in your string.
Demo
avoiding regexp you could use some string function eg:
SELECT LENGTH(':"postalCode";s:4:"3150"') - LOCATE(':', REVERSE(':"postalCode";s:4:"3150"'))+1
from dual ;
or
SELECT LENGTH(col_name) - LOCATE(':', REVERSE(col_name))+1
from my_table ;
It also work with 2 times SUBSTRING_INDEX
SELECT
SUBSTRING_INDEX (SUBSTRING_INDEX( ':"postalCode";s:4:"3150";', '"',-2) , '"', 1);
I want to do something like that
SELECT
id,
num
FROM
sometable
WHERE
num IN (REPLACE ('K-123, K-456, K-678', 'K-', ''));
but:
(REPLACE ('K-123, K-456, K-678', 'K-', ''))
returns: '123, 456, 678',
not as I expected: '123', '456', '678'
So, is it possible to make list of elements after REPLACE() for use that results as an arguments IN()?
Thank you.
You can use find_in_set():
where find_in_set(num, replace(replace('K-123, K-456, K-678', 'K-', ''), ', ', ',') ) > 0
I have a query which returns a field with a set of comma separated values. I would like to get the first three of these values into separate columns in the query result.
I can get the first, using SUBSTRING_INDEX but how can I get the other two?
SELECT
'aaaaa, bbbbb, ccccc',
SUBSTRING_INDEX('aaaaa, bbbbb, ccccc', ',', 1) AS column_one
EDIT - Oops, sorry forgot to mention. The value I want to split could have more (or less) than three strings to extract.
For example, the above string could easily be 'aaaaa' or 'aaaaa, bbbbb, ccccc, ddddd, eeeee'.
In each case, I only need the first three (or however many exist).
Any advice appreciated.
Thanks.
You could use SUBSTRING_INDEX twice, the second one with -1 parameter:
SELECT
'aaaaa, bbbbb, ccccc',
SUBSTRING_INDEX('aaaaa, bbbbb, ccccc', ',', 1) AS column_one,
SUBSTRING_INDEX(SUBSTRING_INDEX('aaaaa, bbbbb, ccccc', ',', 2), ',', -1) AS column_two,
SUBSTRING_INDEX(SUBSTRING_INDEX('aaaaa, bbbbb, ccccc', ',', 3), ',', -1) AS column_three
If the parameter is negative, everything to the right of the final delimiter (counting from the right) is returned. Eg.
SUBSTRING_INDEX('aaaaa, bbbbb, ccccc', ',', 2) will return aaaaa, bbbbb
SUBSTRING_INDEX(aaaaa, bbbbb, ',', -1) will then return bbbbb
You also might want to use ', ' as a delimiter, or TRIM the result.
Please see fiddle here.
Edit
If you want to consider strings that might have less than three values, you could use something like this:
SELECT
s,
SUBSTRING_INDEX(s, ',', 1) AS column_one,
CASE WHEN LENGTH(s)-LENGTH(Replace(s, ',', ''))>0
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(s, ',', 2), ',', -1)
ELSE NULL END AS column_two,
CASE WHEN LENGTH(s)-LENGTH(Replace(s, ',', ''))>1
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(s, ',', 3), ',', -1)
ELSE NULL END AS column_three
FROM
strings
Please see fiddle here.
I have a column that has comma separated data:
1,2,3
3,2,1
4,5,6
5,5,5
I'm trying to run a search that would query each value of the CSV string individually.
0<first<5 and 1<second<3 and 2<third<4
I get that I could return all queries and split it myself and compare it myself. I'm curious if there is a way to do this so MySQL does that processing work.
Thanks!
Use
substring_index(`column`,',',1) ==> first value
substring_index(substring_index(`column`,',',-2),',',1)=> second value
substring_index(substring_index(`column`,',',-1),',',1)=> third value
in your where clause.
SELECT * FROM `table`
WHERE
substring_index(`column`,',',1)<0
AND
substring_index(`column`,',',1)>5
It seems to work:
substring_index ( substring_index ( context,',',1 ), ',', -1)
substring_index ( substring_index ( context,',',2 ), ',', -1)
substring_index ( substring_index ( context,',',3 ), ',', -1)
substring_index ( substring_index ( context,',',4 ), ',', -1)
it means 1st value, 2nd, 3rd, etc.
Explanation:
The inner substring_index returns the first n values that are comma separated. So if your original string is "34,7,23,89", substring_index( context,',', 3) returns "34,7,23".
The outer substring_index takes the value returned by the inner substring_index and the -1 allows you to take the last value. So you get "23" from the "34,7,23".
Instead of -1 if you specify -2, you'll get "7,23", because it took the last two values.
Example:
select * from MyTable where substring_index(substring_index(prices,',',1),',',-1)=3382;
Here, prices is the name of a column in MyTable.
Usually substring_index does what you want:
mysql> select substring_index("foo#gmail.com","#",-1);
+-----------------------------------------+
| substring_index("foo#gmail.com","#",-1) |
+-----------------------------------------+
| gmail.com |
+-----------------------------------------+
1 row in set (0.00 sec)
You may get what you want by using the MySQL REGEXP or LIKE.
See the MySQL Docs on Pattern Matching
As an addendum to this, I've strings of the form:
Some words 303
where I'd like to split off the numerical part from the tail of the string.
This seems to point to a possible solution:
http://lists.mysql.com/mysql/222421
The problem however, is that you only get the answer "yes, it matches", and not the start index of the regexp match.
Here is another variant I posted on related question. The REGEX check to see if you are out of bounds is useful, so for a table column you would put it in the where clause.
SET #Array = 'one,two,three,four';
SET #ArrayIndex = 2;
SELECT CASE
WHEN #Array REGEXP CONCAT('((,).*){',#ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(#Array,',',#ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
SUBSTRING_INDEX(string, delim, n) returns the first n
SUBSTRING_INDEX(string, delim, -1) returns the last only
REGEXP '((delim).*){n}' checks if there are n delimiters (i.e. you are in bounds)
Building on #Oleksiy's answer, here is one that can work with strings of variable segment lengths (within reasonable limits), for example comma-separated addresses:
SELECT substring_index ( substring_index ( address,',',1 ), ',', -1) AS address_line_1,
IF(address_parts > 1, substring_index ( substring_index ( address,',',2 ), ',', -1), '') AS address_line_2,
IF(address_parts > 2, substring_index ( substring_index ( address,',',3 ), ',', -1), '') AS address_line_3,
IF(address_parts > 3, substring_index ( substring_index ( address,',',4 ), ',', -1), '') AS address_line_4,
IF(address_parts > 4, substring_index ( substring_index ( address,',',5 ), ',', -1), '') AS address_line_5
FROM (
SELECT address, LENGTH(address) - LENGTH(REPLACE(address, ',', '')) AS address_parts
FROM mytable
) AS addresses
It's working..
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table_name group by new_col;
I have a column that has comma separated data:
1,2,3
3,2,1
4,5,6
5,5,5
I'm trying to run a search that would query each value of the CSV string individually.
0<first<5 and 1<second<3 and 2<third<4
I get that I could return all queries and split it myself and compare it myself. I'm curious if there is a way to do this so MySQL does that processing work.
Thanks!
Use
substring_index(`column`,',',1) ==> first value
substring_index(substring_index(`column`,',',-2),',',1)=> second value
substring_index(substring_index(`column`,',',-1),',',1)=> third value
in your where clause.
SELECT * FROM `table`
WHERE
substring_index(`column`,',',1)<0
AND
substring_index(`column`,',',1)>5
It seems to work:
substring_index ( substring_index ( context,',',1 ), ',', -1)
substring_index ( substring_index ( context,',',2 ), ',', -1)
substring_index ( substring_index ( context,',',3 ), ',', -1)
substring_index ( substring_index ( context,',',4 ), ',', -1)
it means 1st value, 2nd, 3rd, etc.
Explanation:
The inner substring_index returns the first n values that are comma separated. So if your original string is "34,7,23,89", substring_index( context,',', 3) returns "34,7,23".
The outer substring_index takes the value returned by the inner substring_index and the -1 allows you to take the last value. So you get "23" from the "34,7,23".
Instead of -1 if you specify -2, you'll get "7,23", because it took the last two values.
Example:
select * from MyTable where substring_index(substring_index(prices,',',1),',',-1)=3382;
Here, prices is the name of a column in MyTable.
Usually substring_index does what you want:
mysql> select substring_index("foo#gmail.com","#",-1);
+-----------------------------------------+
| substring_index("foo#gmail.com","#",-1) |
+-----------------------------------------+
| gmail.com |
+-----------------------------------------+
1 row in set (0.00 sec)
You may get what you want by using the MySQL REGEXP or LIKE.
See the MySQL Docs on Pattern Matching
As an addendum to this, I've strings of the form:
Some words 303
where I'd like to split off the numerical part from the tail of the string.
This seems to point to a possible solution:
http://lists.mysql.com/mysql/222421
The problem however, is that you only get the answer "yes, it matches", and not the start index of the regexp match.
Here is another variant I posted on related question. The REGEX check to see if you are out of bounds is useful, so for a table column you would put it in the where clause.
SET #Array = 'one,two,three,four';
SET #ArrayIndex = 2;
SELECT CASE
WHEN #Array REGEXP CONCAT('((,).*){',#ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(#Array,',',#ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
SUBSTRING_INDEX(string, delim, n) returns the first n
SUBSTRING_INDEX(string, delim, -1) returns the last only
REGEXP '((delim).*){n}' checks if there are n delimiters (i.e. you are in bounds)
Building on #Oleksiy's answer, here is one that can work with strings of variable segment lengths (within reasonable limits), for example comma-separated addresses:
SELECT substring_index ( substring_index ( address,',',1 ), ',', -1) AS address_line_1,
IF(address_parts > 1, substring_index ( substring_index ( address,',',2 ), ',', -1), '') AS address_line_2,
IF(address_parts > 2, substring_index ( substring_index ( address,',',3 ), ',', -1), '') AS address_line_3,
IF(address_parts > 3, substring_index ( substring_index ( address,',',4 ), ',', -1), '') AS address_line_4,
IF(address_parts > 4, substring_index ( substring_index ( address,',',5 ), ',', -1), '') AS address_line_5
FROM (
SELECT address, LENGTH(address) - LENGTH(REPLACE(address, ',', '')) AS address_parts
FROM mytable
) AS addresses
It's working..
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table_name group by new_col;