I had a problem in using a string-comma-separated-value returned from a query in an “IN” statement. I used the IDs from one table, concat them into a comma separated value and insert them into another table. Baaaad idea… Now when I query that value, I can’t use it directly into an “IN” statement to retrieve their real values since its a string being returned from the query, the “IN” statement will not compare all the values inside as a set, but it will compare it as a string.
SELECT value FROM my_table WHERE my_id IN (‘1, 2, 3’) is NOT equivalent to SELECT value FROM my_table WHERE my_id IN (‘1’, ‘2’, ‘3’)
So, if you have a table containing values 1 to 3, the first query will return only 1 while the second query will return all values; 1, 2 and 3.
I Googled around and found out that MySQL does not have a native equivalent of PHP’s explode() function. Crap… I had to do it the hard war and create a MySQL stored function to ‘explode’ the values from its delimiter, query the right value from the other table using the exploded IDs, concat them back together and return them as a string.
Below is the function I was able to patch together from different codes I found in the MySQL forum. I added comments below as to make things clearer. I named the function splitAndTranslate since that’s what I was really trying to implement. You can make up your own modifications and function name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
DELIMITER // DROP FUNCTION IF EXISTS `splitAndTranslate` // CREATE FUNCTION splitAndTranslate(str TEXT, delim VARCHAR(124)) RETURNS TEXT DETERMINISTIC BEGIN DECLARE i INT DEFAULT 0; -- total number of delimiters DECLARE ctr INT DEFAULT 0; -- counter for the loop DECLARE str_len INT; -- string length,self explanatory DECLARE out_str text DEFAULT ''; -- return string holder DECLARE temp_str text DEFAULT ''; -- temporary string holder DECLARE temp_val VARCHAR(255) DEFAULT ''; -- temporary string holder for query -- get length SET str_len=LENGTH(str); SET i = (LENGTH(str)-LENGTH(REPLACE(str, delim, '')))/LENGTH(delim) + 1; -- get total number delimeters and add 1 -- add 1 since total separated values are 1 more than the number of delimiters -- start of while loop WHILE(ctr<i) DO -- add 1 to the counter, which will also be used to get the value of the string SET ctr=ctr+1; -- get value separated by delimiter using ctr as the index SET temp_str = REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, ctr), LENGTH(SUBSTRING_INDEX(str, delim,ctr - 1)) + 1), delim, ''); -- query real value and insert into temporary value holder, temp_str contains the exploded ID SELECT <real_value_column> INTO temp_val FROM <my_table> WHERE <table_id>=temp_str; -- concat real value into output string separated by delimiter SET out_str=CONCAT(out_str, temp_val, ','); END WHILE; -- end of while loop -- trim delimiter from end of string SET out_str=TRIM(TRAILING delim FROM out_str); RETURN(out_str); -- return END//
After creating the stored function, you can now use it normally like any MySQL function inside a query. So what I now do with the new function is…
SELECT splitAndTranslate( g.comma_separated_ids ) real_values FROM my_group_table g;
Thanks to Chris Stubben in the MySQL Forum, I used and modified his code to fit my need.