MySQL - Get first 3 comma separated values - mysql

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.

Related

Replace the special characters

data = "Qwsdyz_qwrbc_bcD_qwEr"
What I need is:
remove all the _
all characters to be in lower
the starting letter should be caps for all the 4 like this (QwsdyzQwrbcBcdQwer)
whatever changes made in above statement should't change the result like if we changed like Qwsdqwqyz_qwrwqeqwebc_bcqwD_qqwwEr_dadakjas i need the result like QesdqwqyzQwrwqeqwebcBcqwdQqwwerDasakjas
Please help me with MySQL coding.
set #data="Qwsdyz_qwrbc_bcD_qwEr";
select lower(SUBSTRING_INDEX(#data,"_",1)) into #data1;
select ucase(left(SUBSTRING_INDEX(#data,"_",2),1)) into #data2;
select lower(SUBSTRING_INDEX(#data,"_",2)) into #data3;
select substring(reverse(SUBSTRING_INDEX(reverse(#data3),"_",1)),2) into #data4;
select reverse((lower(SUBSTRING_INDEX(#data,"_",3)))) into #data5;
select (reverse(SUBSTRING_INDEX(#data5,"_",1))) into #data6;
select ucase(left(#data6,1)) into #data7;
select substring(#data6,2) into #data8;
select reverse(#data) into #data9;
select reverse(lower(SUBSTRING_INDEX(#data9,"_",1))) into #data10;
select ucase(left(#data10,1)) into #data11;
select substring(#data10,2) into #data12;
select concat(#data1,#data2,#data4,#data7,#data8,#data11,#data12) data;
You can use split functions replied in this question. Do sub-string and find every splited strings first character with UPPER() function do it upper character and LOWER() function do other characters to lowercase. And finally join with CONCAT() function.
This is just a messy concat() and substring_index():
select concat(concat(upper(left(lower(substring_index(data, '_', 1)), 1)),
lower(substr(lower(substring_index(data, '_', 1)), 2))
),
concat(upper(left(lower(substring_index(substring_index(data, '_', 2), '_', -1)), 1)),
lower(substr(lower(substring_index(substring_index(data, '_', 2), '_', -1)), 2))
),
concat(upper(left(lower(substring_index(substring_index(data, '_', 3), '_', -1)), 1)),
lower(substr(lower(substring_index(substring_index(data, '_', 3), '_', -1)), 2))
),
concat(upper(left(lower(substring_index(substring_index(data, '_', 4), '_', -1)), 1)),
lower(substr(lower(substring_index(substring_index(data, '_', 4), '_', -1)), 2))
)
)
from (select 'Qwsdyz_qwrbc_bcD_qwEr' as data) x
SQL is not optimized for string manipulations. I would advise you to do this in another tool, such as Python, if that is possible.
Here is a db<>fiddle.

MySQL - Get the values between delimiters in a string

I have a comma separated string like
1,2,3,4,5 or
1,2,3,4,5,5,8 or 1,2,2,6,6,7,8
I want anything that is between the third comma and last comma leaving out the last element.
The result of 1,2,3,4,5 should be 4.
The result of 1,2,3,4,5,5,8 should be 4,5,5.
The result of 1,2,2,6,6,7,8 should be 6,6,7.
I tried with the below. But it fails when the 3rd value is same as 1st or 2nd value.
SUBSTRING( LEFT(string, LENGTH(string)
- LOCATE(',', REVERSE(string)))
, LOCATE(SUBSTRING_INDEX(SUBSTRING_INDEX(string, ',', 3), string ))
Hmmmm. To get rid of the last element:
select substr(string, 1, length(string) - substring_index(string, ',', -1) - 1)
Then to get rid of the first three:
select substr(substr(string, 1, length(string) - substring_index(string, ',', -1) - 1),
substring_index(string, ',', 3) + 1
)
Finally this is what I did to resolve. Comments are welcome.
select SUBSTRING(#String,length(SUBSTRING_INDEX(#String,',',3))+2,
(length(#String) - length(SUBSTRING_INDEX(#String,',',-1))-length(SUBSTRING_INDEX(#String,',',3)) -2));

alternative to splitting MySQL query result in multiple rows [duplicate]

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;

mysql split string [duplicate]

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;

Can MySQL split a column?

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;