I have String asdasdwdfef,rgrgtggt,weef
and i want output like in table format as shown below
id decription
1 asdasdwdfef
2 rgrgtgg
Requirements: split a 'delimited' column into rows (a table).
Why? You can use all the SQL Aggregate functions to process the rows.
Working SQLFiddle
Related questions that use this code:
Count number of unique characters in a string
Can I resolve this with pure mysql? (joining on ';' separated values in a column)
I chose to use:
table of integers (integersequence) which when 'inner joined' or 'cross joined' (same thing) to another table will generate rows which are certain to have a unique sequence number starting from 1. This is just using what RDBMS engines are required to do.
why a table of integers?: It is small and will get loaded into the cache. It is easy to understand.
Rather than have lots of code in the query that obscures what it actually does. I use functions that do one job. It simplifies the main query and can be tested and checked separately. I am only concerned about ease of maintenance and understanding at this point.
The example here is for one string. However, It can be easily expanded to a table of delimited strings of various sizes. The 'cross join' will create all the possible options of index starting from 1 when joining to integersequence
(i really need to use another name :-/).
So, the query:
SET @StrToParse = "asdasdwdfef,rgrgtggt,weef";
/* example */
select integerseries.id,
count_in_set(@StrToParse, ','),
value_in_set(@StrToParse, ',', integerseries.id)
from integerseries
where integerseries.id <= count_in_set(@StrToParse, ',');
The output:
PositionOfString, CountOfCommaDelimitedStrings, StringAtThatPosition
1 3 asdasdwdfef
2 3 rgrgtggt
3 3 weef
Now, how do we get those values:
I chose to use two functions:
The names are related to the mysql
function 'FIND_IN_SET'.
1) The COUNT_IN_SET
function: returns the count of character delimited items
in the column.
CREATE FUNCTION `COUNT_IN_SET`(haystack VARCHAR(1024),
delim CHAR(1)
) RETURNS INTEGER
BEGIN
RETURN CHAR_LENGTH(haystack) - CHAR_LENGTH( REPLACE(haystack, delim, '')) + 1;
END$$
2) The VALUE_IN_SET
function: treats the delimited list
as a one based array
and returns the value at the given 'index'.
CREATE FUNCTION `VALUE_IN_SET`(haystack VARCHAR(1024),
delim CHAR(1),
which INTEGER
) RETURNS VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci
BEGIN
RETURN SUBSTRING_INDEX(SUBSTRING_INDEX(haystack, delim, which),
delim,
-1);
END$$
The intereseries table - see (Tally tables)
CREATE TABLE `integerseries` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Data for the table `integerseries` */
insert into `integerseries`(`id`) values (1);
insert into `integerseries`(`id`) values (2);
insert into `integerseries`(`id`) values (3);
insert into `integerseries`(`id`) values (4);
insert into `integerseries`(`id`) values (5);
insert into `integerseries`(`id`) values (6);
insert into `integerseries`(`id`) values (7);
insert into `integerseries`(`id`) values (8);
insert into `integerseries`(`id`) values (9);
insert into `integerseries`(`id`) values (10);
I got the answer
First create new function
CREATE FUNCTION SPLIT_STR(x VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1), delim, '');
Then create stored procedure
DELIMITER ;;
CREATE PROCEDURE Split(in fullstr varchar(255))
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DROP TABLE IF EXISTS my_temp_table;
CREATE temporary TABLE my_temp_table(ID INT AUTO_INCREMENT NOT NULL, description text, primary key(ID));
simple_loop: LOOP
SET a=a+1;
SET str=SPLIT_STR(fullstr,",",a);
IF str='' THEN
LEAVE simple_loop;
END IF;
#Do Inserts into temp table here with str going into the row
insert into my_temp_table (description) values (str);
END LOOP simple_loop;
select * from my_temp_table;
END
After that when i call it by call Split('asas,d,sddf,dfd');
it gives me the output that what i want.
Thanx for every suggestion.