SQL split values to multiple rows










53















I have table :



id | name 
1 | a,b,c
2 | b


i want output like this :



id | name 
1 | a
1 | b
1 | c
2 | b









share|improve this question



















  • 1





    Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

    – FSou1
    Jul 30 '13 at 9:00






  • 5





    it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

    – Graham Griffiths
    Jul 30 '13 at 9:08











  • @GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

    – Veverke
    Jan 11 '17 at 9:08
















53















I have table :



id | name 
1 | a,b,c
2 | b


i want output like this :



id | name 
1 | a
1 | b
1 | c
2 | b









share|improve this question



















  • 1





    Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

    – FSou1
    Jul 30 '13 at 9:00






  • 5





    it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

    – Graham Griffiths
    Jul 30 '13 at 9:08











  • @GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

    – Veverke
    Jan 11 '17 at 9:08














53












53








53


19






I have table :



id | name 
1 | a,b,c
2 | b


i want output like this :



id | name 
1 | a
1 | b
1 | c
2 | b









share|improve this question
















I have table :



id | name 
1 | a,b,c
2 | b


i want output like this :



id | name 
1 | a
1 | b
1 | c
2 | b






mysql sql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jul 30 '13 at 8:59









slavoo

3,978122936




3,978122936










asked Jul 30 '13 at 8:57









AFDAFD

283138




283138







  • 1





    Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

    – FSou1
    Jul 30 '13 at 9:00






  • 5





    it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

    – Graham Griffiths
    Jul 30 '13 at 9:08











  • @GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

    – Veverke
    Jan 11 '17 at 9:08













  • 1





    Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

    – FSou1
    Jul 30 '13 at 9:00






  • 5





    it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

    – Graham Griffiths
    Jul 30 '13 at 9:08











  • @GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

    – Veverke
    Jan 11 '17 at 9:08








1




1





Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

– FSou1
Jul 30 '13 at 9:00





Check this: marcogoncalves.com/2011/03/mysql-split-column-string-into-rows

– FSou1
Jul 30 '13 at 9:00




5




5





it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

– Graham Griffiths
Jul 30 '13 at 9:08





it's generally considered bad practice to store multiple values in the same database column. This best practice - normalisation - generally makes your database work better in future. It is explained here (or read up on 'normalisation') : stackoverflow.com/questions/2331838/…

– Graham Griffiths
Jul 30 '13 at 9:08













@GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

– Veverke
Jan 11 '17 at 9:08






@GrahamGriffiths: I would agree with you, at least this is what academic knowledge tells. However, in my company there are lots of instances where they do this kind of stuff (storing multiple values in a delimited string fashion) in a single column, and their claim is that it is more efficient (join-free, and the processing required is not costly). I honestly do not know which point should be preferred.

– Veverke
Jan 11 '17 at 9:08













5 Answers
5






active

oldest

votes


















82














If you can create a numbers table, that contains numbers from 1 to the maximum fields to split, you could use a solution like this:



select
tablename.id,
SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
from
numbers inner join tablename
on CHAR_LENGTH(tablename.name)
-CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
order by
id, n


Please see fiddle here.



If you cannot create a table, then a solution can be this:



select
tablename.id,
SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
from
(select 1 n union all
select 2 union all select 3 union all
select 4 union all select 5) numbers INNER JOIN tablename
on CHAR_LENGTH(tablename.name)
-CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
order by
id, n


an example fiddle is here.






share|improve this answer

























  • thanks,using 2 table ? i want just 1 table

    – AFD
    Jul 30 '13 at 9:26







  • 11





    @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

    – fthiella
    Jul 30 '13 at 9:33











  • An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

    – Bret Weinraub
    Jul 27 '16 at 21:04







  • 1





    As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

    – Drew
    Sep 26 '16 at 7:40











  • How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

    – Remi Sture
    Nov 22 '16 at 8:29


















5














I have take the reference from here with changed column name.



DELIMITER $$

CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
RETURNS VARCHAR(65000)
BEGIN
DECLARE output VARCHAR(65000);
SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
, LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
, delim
, '');
IF output = '' THEN SET output = null; END IF;
RETURN output;
END $$


CREATE PROCEDURE BadTableToGoodTable()
BEGIN
DECLARE i INTEGER;

SET i = 1;
REPEAT
INSERT INTO GoodTable (id, name)
SELECT id, strSplit(name, ',', i) FROM BadTable
WHERE strSplit(name, ',', i) IS NOT NULL;
SET i = i + 1;
UNTIL ROW_COUNT() = 0
END REPEAT;
END $$

DELIMITER ;





share|improve this answer

























  • thanks,but im only have privilidge readonly

    – AFD
    Jul 30 '13 at 9:25



















3














My variant: stored procedure that takes table name, field names and delimiter as arguments. Inspired by post http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/



delimiter $$

DROP PROCEDURE IF EXISTS split_value_into_multiple_rows $$
CREATE PROCEDURE split_value_into_multiple_rows(tablename VARCHAR(20),
id_column VARCHAR(20), value_column VARCHAR(20), delim CHAR(1))
BEGIN
DECLARE id INT DEFAULT 0;
DECLARE value VARCHAR(255);
DECLARE occurrences INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE splitted_value VARCHAR(255);
DECLARE done INT DEFAULT 0;
DECLARE cur CURSOR FOR SELECT tmp_table1.id, tmp_table1.value FROM
tmp_table1 WHERE tmp_table1.value IS NOT NULL AND tmp_table1.value != '';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

SET @expr = CONCAT('CREATE TEMPORARY TABLE tmp_table1 (id INT NOT NULL, value VARCHAR(255)) ENGINE=Memory SELECT ',
id_column,' id, ', value_column,' value FROM ',tablename);
PREPARE stmt FROM @expr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

DROP TEMPORARY TABLE IF EXISTS tmp_table2;
CREATE TEMPORARY TABLE tmp_table2 (id INT NOT NULL, value VARCHAR(255) NOT NULL) ENGINE=Memory;

OPEN cur;
read_loop: LOOP
FETCH cur INTO id, value;
IF done THEN
LEAVE read_loop;
END IF;

SET occurrences = (SELECT CHAR_LENGTH(value) -
CHAR_LENGTH(REPLACE(value, delim, '')) + 1);
SET i=1;
WHILE i <= occurrences DO
SET splitted_value = (SELECT TRIM(SUBSTRING_INDEX(
SUBSTRING_INDEX(value, delim, i), delim, -1)));
INSERT INTO tmp_table2 VALUES (id, splitted_value);
SET i = i + 1;
END WHILE;
END LOOP;

SELECT * FROM tmp_table2;
CLOSE cur;
DROP TEMPORARY TABLE tmp_table1;
END; $$

delimiter ;


Usage example (normalization):



CALL split_value_into_multiple_rows('my_contacts', 'contact_id', 'interests', ',');

CREATE TABLE interests (
interest_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
interest VARCHAR(30) NOT NULL
) SELECT DISTINCT value interest FROM tmp_table2;

CREATE TABLE contact_interest (
contact_id INT NOT NULL,
interest_id INT NOT NULL,
CONSTRAINT fk_contact_interest_my_contacts_contact_id FOREIGN KEY (contact_id) REFERENCES my_contacts (contact_id),
CONSTRAINT fk_contact_interest_interests_interest_id FOREIGN KEY (interest_id) REFERENCES interests (interest_id)
) SELECT my_contacts.contact_id, interests.interest_id
FROM my_contacts, tmp_table2, interests
WHERE my_contacts.contact_id = tmp_table2.id AND interests.interest = tmp_table2.value;





share|improve this answer

























  • Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

    – raviabhiram
    Feb 22 at 6:29


















1














CREATE PROCEDURE `getVal`()
BEGIN
declare r_len integer;
declare r_id integer;
declare r_val varchar(20);
declare i integer;
DECLARE found_row int(10);
DECLARE row CURSOR FOR select length(replace(val,"|","")),id,val from split;
create table x(id int,name varchar(20));
open row;
select FOUND_ROWS() into found_row ;
read_loop: LOOP
IF found_row = 0 THEN
LEAVE read_loop;
END IF;
set i = 1;
FETCH row INTO r_len,r_id,r_val;
label1: LOOP
IF i <= r_len THEN
insert into x values( r_id,SUBSTRING(replace(r_val,"|",""),i,1));
SET i = i + 1;
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
set found_row = found_row - 1;
END LOOP;
close row;
select * from x;
drop table x;
END





share|improve this answer






























    -1














    Here is my solution



    -- Create the maximum number of words we want to pick (indexes in n)
    with recursive n(i) as (
    select
    1 i
    union all
    select i+1 from n where i < 1000
    )
    select distinct
    s.id,
    s.oaddress,
    -- n.i,
    -- use the index to pick the nth word, the last words will always repeat. Remove the duplicates with distinct
    if(instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' ') > 0,
    reverse(substr(reverse(trim(substring_index(s.oaddress,' ',n.i))),1,
    instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' '))),
    trim(substring_index(s.oaddress,' ',n.i))) oth
    from
    app_schools s,
    n





    share|improve this answer






















      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f17942508%2fsql-split-values-to-multiple-rows%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      82














      If you can create a numbers table, that contains numbers from 1 to the maximum fields to split, you could use a solution like this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      numbers inner join tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      Please see fiddle here.



      If you cannot create a table, then a solution can be this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      (select 1 n union all
      select 2 union all select 3 union all
      select 4 union all select 5) numbers INNER JOIN tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      an example fiddle is here.






      share|improve this answer

























      • thanks,using 2 table ? i want just 1 table

        – AFD
        Jul 30 '13 at 9:26







      • 11





        @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

        – fthiella
        Jul 30 '13 at 9:33











      • An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

        – Bret Weinraub
        Jul 27 '16 at 21:04







      • 1





        As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

        – Drew
        Sep 26 '16 at 7:40











      • How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

        – Remi Sture
        Nov 22 '16 at 8:29















      82














      If you can create a numbers table, that contains numbers from 1 to the maximum fields to split, you could use a solution like this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      numbers inner join tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      Please see fiddle here.



      If you cannot create a table, then a solution can be this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      (select 1 n union all
      select 2 union all select 3 union all
      select 4 union all select 5) numbers INNER JOIN tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      an example fiddle is here.






      share|improve this answer

























      • thanks,using 2 table ? i want just 1 table

        – AFD
        Jul 30 '13 at 9:26







      • 11





        @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

        – fthiella
        Jul 30 '13 at 9:33











      • An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

        – Bret Weinraub
        Jul 27 '16 at 21:04







      • 1





        As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

        – Drew
        Sep 26 '16 at 7:40











      • How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

        – Remi Sture
        Nov 22 '16 at 8:29













      82












      82








      82







      If you can create a numbers table, that contains numbers from 1 to the maximum fields to split, you could use a solution like this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      numbers inner join tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      Please see fiddle here.



      If you cannot create a table, then a solution can be this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      (select 1 n union all
      select 2 union all select 3 union all
      select 4 union all select 5) numbers INNER JOIN tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      an example fiddle is here.






      share|improve this answer















      If you can create a numbers table, that contains numbers from 1 to the maximum fields to split, you could use a solution like this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      numbers inner join tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      Please see fiddle here.



      If you cannot create a table, then a solution can be this:



      select
      tablename.id,
      SUBSTRING_INDEX(SUBSTRING_INDEX(tablename.name, ',', numbers.n), ',', -1) name
      from
      (select 1 n union all
      select 2 union all select 3 union all
      select 4 union all select 5) numbers INNER JOIN tablename
      on CHAR_LENGTH(tablename.name)
      -CHAR_LENGTH(REPLACE(tablename.name, ',', ''))>=numbers.n-1
      order by
      id, n


      an example fiddle is here.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Feb 1 '16 at 7:33

























      answered Jul 30 '13 at 9:05









      fthiellafthiella

      39.9k126591




      39.9k126591












      • thanks,using 2 table ? i want just 1 table

        – AFD
        Jul 30 '13 at 9:26







      • 11





        @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

        – fthiella
        Jul 30 '13 at 9:33











      • An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

        – Bret Weinraub
        Jul 27 '16 at 21:04







      • 1





        As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

        – Drew
        Sep 26 '16 at 7:40











      • How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

        – Remi Sture
        Nov 22 '16 at 8:29

















      • thanks,using 2 table ? i want just 1 table

        – AFD
        Jul 30 '13 at 9:26







      • 11





        @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

        – fthiella
        Jul 30 '13 at 9:33











      • An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

        – Bret Weinraub
        Jul 27 '16 at 21:04







      • 1





        As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

        – Drew
        Sep 26 '16 at 7:40











      • How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

        – Remi Sture
        Nov 22 '16 at 8:29
















      thanks,using 2 table ? i want just 1 table

      – AFD
      Jul 30 '13 at 9:26






      thanks,using 2 table ? i want just 1 table

      – AFD
      Jul 30 '13 at 9:26





      11




      11





      @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

      – fthiella
      Jul 30 '13 at 9:33





      @user2577038 you could do it without a numbers table, see it here sqlfiddle.com/#!2/a213e4/1

      – fthiella
      Jul 30 '13 at 9:33













      An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

      – Bret Weinraub
      Jul 27 '16 at 21:04






      An important thing to note is in the second example, the maximum number of "fields" separated by comma is 5. You can check the # of occurrences in a string via a method like the one here: stackoverflow.com/questions/12344795/…. Keep adding 'select [number] union all' clauses to the 'numbers' inline view until the number of rows returned stops increasing.

      – Bret Weinraub
      Jul 27 '16 at 21:04





      1




      1





      As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

      – Drew
      Sep 26 '16 at 7:40





      As usual I keep stumbling into your useful code. If anyone wants the quick way to create a table similar to the top chunk shown here, here is a link using this routine here. That op was for a single string not a table of them.

      – Drew
      Sep 26 '16 at 7:40













      How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

      – Remi Sture
      Nov 22 '16 at 8:29





      How would a SQLite version of this look like? I get the following error: could not prepare statement (1 no such function: SUBSTRING_INDEX)

      – Remi Sture
      Nov 22 '16 at 8:29













      5














      I have take the reference from here with changed column name.



      DELIMITER $$

      CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
      RETURNS VARCHAR(65000)
      BEGIN
      DECLARE output VARCHAR(65000);
      SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
      , LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
      , delim
      , '');
      IF output = '' THEN SET output = null; END IF;
      RETURN output;
      END $$


      CREATE PROCEDURE BadTableToGoodTable()
      BEGIN
      DECLARE i INTEGER;

      SET i = 1;
      REPEAT
      INSERT INTO GoodTable (id, name)
      SELECT id, strSplit(name, ',', i) FROM BadTable
      WHERE strSplit(name, ',', i) IS NOT NULL;
      SET i = i + 1;
      UNTIL ROW_COUNT() = 0
      END REPEAT;
      END $$

      DELIMITER ;





      share|improve this answer

























      • thanks,but im only have privilidge readonly

        – AFD
        Jul 30 '13 at 9:25
















      5














      I have take the reference from here with changed column name.



      DELIMITER $$

      CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
      RETURNS VARCHAR(65000)
      BEGIN
      DECLARE output VARCHAR(65000);
      SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
      , LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
      , delim
      , '');
      IF output = '' THEN SET output = null; END IF;
      RETURN output;
      END $$


      CREATE PROCEDURE BadTableToGoodTable()
      BEGIN
      DECLARE i INTEGER;

      SET i = 1;
      REPEAT
      INSERT INTO GoodTable (id, name)
      SELECT id, strSplit(name, ',', i) FROM BadTable
      WHERE strSplit(name, ',', i) IS NOT NULL;
      SET i = i + 1;
      UNTIL ROW_COUNT() = 0
      END REPEAT;
      END $$

      DELIMITER ;





      share|improve this answer

























      • thanks,but im only have privilidge readonly

        – AFD
        Jul 30 '13 at 9:25














      5












      5








      5







      I have take the reference from here with changed column name.



      DELIMITER $$

      CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
      RETURNS VARCHAR(65000)
      BEGIN
      DECLARE output VARCHAR(65000);
      SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
      , LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
      , delim
      , '');
      IF output = '' THEN SET output = null; END IF;
      RETURN output;
      END $$


      CREATE PROCEDURE BadTableToGoodTable()
      BEGIN
      DECLARE i INTEGER;

      SET i = 1;
      REPEAT
      INSERT INTO GoodTable (id, name)
      SELECT id, strSplit(name, ',', i) FROM BadTable
      WHERE strSplit(name, ',', i) IS NOT NULL;
      SET i = i + 1;
      UNTIL ROW_COUNT() = 0
      END REPEAT;
      END $$

      DELIMITER ;





      share|improve this answer















      I have take the reference from here with changed column name.



      DELIMITER $$

      CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
      RETURNS VARCHAR(65000)
      BEGIN
      DECLARE output VARCHAR(65000);
      SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
      , LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
      , delim
      , '');
      IF output = '' THEN SET output = null; END IF;
      RETURN output;
      END $$


      CREATE PROCEDURE BadTableToGoodTable()
      BEGIN
      DECLARE i INTEGER;

      SET i = 1;
      REPEAT
      INSERT INTO GoodTable (id, name)
      SELECT id, strSplit(name, ',', i) FROM BadTable
      WHERE strSplit(name, ',', i) IS NOT NULL;
      SET i = i + 1;
      UNTIL ROW_COUNT() = 0
      END REPEAT;
      END $$

      DELIMITER ;






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited May 23 '17 at 12:26









      Community

      11




      11










      answered Jul 30 '13 at 9:05









      LuvLuv

      9,320154162




      9,320154162












      • thanks,but im only have privilidge readonly

        – AFD
        Jul 30 '13 at 9:25


















      • thanks,but im only have privilidge readonly

        – AFD
        Jul 30 '13 at 9:25

















      thanks,but im only have privilidge readonly

      – AFD
      Jul 30 '13 at 9:25






      thanks,but im only have privilidge readonly

      – AFD
      Jul 30 '13 at 9:25












      3














      My variant: stored procedure that takes table name, field names and delimiter as arguments. Inspired by post http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/



      delimiter $$

      DROP PROCEDURE IF EXISTS split_value_into_multiple_rows $$
      CREATE PROCEDURE split_value_into_multiple_rows(tablename VARCHAR(20),
      id_column VARCHAR(20), value_column VARCHAR(20), delim CHAR(1))
      BEGIN
      DECLARE id INT DEFAULT 0;
      DECLARE value VARCHAR(255);
      DECLARE occurrences INT DEFAULT 0;
      DECLARE i INT DEFAULT 0;
      DECLARE splitted_value VARCHAR(255);
      DECLARE done INT DEFAULT 0;
      DECLARE cur CURSOR FOR SELECT tmp_table1.id, tmp_table1.value FROM
      tmp_table1 WHERE tmp_table1.value IS NOT NULL AND tmp_table1.value != '';
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

      SET @expr = CONCAT('CREATE TEMPORARY TABLE tmp_table1 (id INT NOT NULL, value VARCHAR(255)) ENGINE=Memory SELECT ',
      id_column,' id, ', value_column,' value FROM ',tablename);
      PREPARE stmt FROM @expr;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;

      DROP TEMPORARY TABLE IF EXISTS tmp_table2;
      CREATE TEMPORARY TABLE tmp_table2 (id INT NOT NULL, value VARCHAR(255) NOT NULL) ENGINE=Memory;

      OPEN cur;
      read_loop: LOOP
      FETCH cur INTO id, value;
      IF done THEN
      LEAVE read_loop;
      END IF;

      SET occurrences = (SELECT CHAR_LENGTH(value) -
      CHAR_LENGTH(REPLACE(value, delim, '')) + 1);
      SET i=1;
      WHILE i <= occurrences DO
      SET splitted_value = (SELECT TRIM(SUBSTRING_INDEX(
      SUBSTRING_INDEX(value, delim, i), delim, -1)));
      INSERT INTO tmp_table2 VALUES (id, splitted_value);
      SET i = i + 1;
      END WHILE;
      END LOOP;

      SELECT * FROM tmp_table2;
      CLOSE cur;
      DROP TEMPORARY TABLE tmp_table1;
      END; $$

      delimiter ;


      Usage example (normalization):



      CALL split_value_into_multiple_rows('my_contacts', 'contact_id', 'interests', ',');

      CREATE TABLE interests (
      interest_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      interest VARCHAR(30) NOT NULL
      ) SELECT DISTINCT value interest FROM tmp_table2;

      CREATE TABLE contact_interest (
      contact_id INT NOT NULL,
      interest_id INT NOT NULL,
      CONSTRAINT fk_contact_interest_my_contacts_contact_id FOREIGN KEY (contact_id) REFERENCES my_contacts (contact_id),
      CONSTRAINT fk_contact_interest_interests_interest_id FOREIGN KEY (interest_id) REFERENCES interests (interest_id)
      ) SELECT my_contacts.contact_id, interests.interest_id
      FROM my_contacts, tmp_table2, interests
      WHERE my_contacts.contact_id = tmp_table2.id AND interests.interest = tmp_table2.value;





      share|improve this answer

























      • Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

        – raviabhiram
        Feb 22 at 6:29















      3














      My variant: stored procedure that takes table name, field names and delimiter as arguments. Inspired by post http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/



      delimiter $$

      DROP PROCEDURE IF EXISTS split_value_into_multiple_rows $$
      CREATE PROCEDURE split_value_into_multiple_rows(tablename VARCHAR(20),
      id_column VARCHAR(20), value_column VARCHAR(20), delim CHAR(1))
      BEGIN
      DECLARE id INT DEFAULT 0;
      DECLARE value VARCHAR(255);
      DECLARE occurrences INT DEFAULT 0;
      DECLARE i INT DEFAULT 0;
      DECLARE splitted_value VARCHAR(255);
      DECLARE done INT DEFAULT 0;
      DECLARE cur CURSOR FOR SELECT tmp_table1.id, tmp_table1.value FROM
      tmp_table1 WHERE tmp_table1.value IS NOT NULL AND tmp_table1.value != '';
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

      SET @expr = CONCAT('CREATE TEMPORARY TABLE tmp_table1 (id INT NOT NULL, value VARCHAR(255)) ENGINE=Memory SELECT ',
      id_column,' id, ', value_column,' value FROM ',tablename);
      PREPARE stmt FROM @expr;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;

      DROP TEMPORARY TABLE IF EXISTS tmp_table2;
      CREATE TEMPORARY TABLE tmp_table2 (id INT NOT NULL, value VARCHAR(255) NOT NULL) ENGINE=Memory;

      OPEN cur;
      read_loop: LOOP
      FETCH cur INTO id, value;
      IF done THEN
      LEAVE read_loop;
      END IF;

      SET occurrences = (SELECT CHAR_LENGTH(value) -
      CHAR_LENGTH(REPLACE(value, delim, '')) + 1);
      SET i=1;
      WHILE i <= occurrences DO
      SET splitted_value = (SELECT TRIM(SUBSTRING_INDEX(
      SUBSTRING_INDEX(value, delim, i), delim, -1)));
      INSERT INTO tmp_table2 VALUES (id, splitted_value);
      SET i = i + 1;
      END WHILE;
      END LOOP;

      SELECT * FROM tmp_table2;
      CLOSE cur;
      DROP TEMPORARY TABLE tmp_table1;
      END; $$

      delimiter ;


      Usage example (normalization):



      CALL split_value_into_multiple_rows('my_contacts', 'contact_id', 'interests', ',');

      CREATE TABLE interests (
      interest_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      interest VARCHAR(30) NOT NULL
      ) SELECT DISTINCT value interest FROM tmp_table2;

      CREATE TABLE contact_interest (
      contact_id INT NOT NULL,
      interest_id INT NOT NULL,
      CONSTRAINT fk_contact_interest_my_contacts_contact_id FOREIGN KEY (contact_id) REFERENCES my_contacts (contact_id),
      CONSTRAINT fk_contact_interest_interests_interest_id FOREIGN KEY (interest_id) REFERENCES interests (interest_id)
      ) SELECT my_contacts.contact_id, interests.interest_id
      FROM my_contacts, tmp_table2, interests
      WHERE my_contacts.contact_id = tmp_table2.id AND interests.interest = tmp_table2.value;





      share|improve this answer

























      • Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

        – raviabhiram
        Feb 22 at 6:29













      3












      3








      3







      My variant: stored procedure that takes table name, field names and delimiter as arguments. Inspired by post http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/



      delimiter $$

      DROP PROCEDURE IF EXISTS split_value_into_multiple_rows $$
      CREATE PROCEDURE split_value_into_multiple_rows(tablename VARCHAR(20),
      id_column VARCHAR(20), value_column VARCHAR(20), delim CHAR(1))
      BEGIN
      DECLARE id INT DEFAULT 0;
      DECLARE value VARCHAR(255);
      DECLARE occurrences INT DEFAULT 0;
      DECLARE i INT DEFAULT 0;
      DECLARE splitted_value VARCHAR(255);
      DECLARE done INT DEFAULT 0;
      DECLARE cur CURSOR FOR SELECT tmp_table1.id, tmp_table1.value FROM
      tmp_table1 WHERE tmp_table1.value IS NOT NULL AND tmp_table1.value != '';
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

      SET @expr = CONCAT('CREATE TEMPORARY TABLE tmp_table1 (id INT NOT NULL, value VARCHAR(255)) ENGINE=Memory SELECT ',
      id_column,' id, ', value_column,' value FROM ',tablename);
      PREPARE stmt FROM @expr;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;

      DROP TEMPORARY TABLE IF EXISTS tmp_table2;
      CREATE TEMPORARY TABLE tmp_table2 (id INT NOT NULL, value VARCHAR(255) NOT NULL) ENGINE=Memory;

      OPEN cur;
      read_loop: LOOP
      FETCH cur INTO id, value;
      IF done THEN
      LEAVE read_loop;
      END IF;

      SET occurrences = (SELECT CHAR_LENGTH(value) -
      CHAR_LENGTH(REPLACE(value, delim, '')) + 1);
      SET i=1;
      WHILE i <= occurrences DO
      SET splitted_value = (SELECT TRIM(SUBSTRING_INDEX(
      SUBSTRING_INDEX(value, delim, i), delim, -1)));
      INSERT INTO tmp_table2 VALUES (id, splitted_value);
      SET i = i + 1;
      END WHILE;
      END LOOP;

      SELECT * FROM tmp_table2;
      CLOSE cur;
      DROP TEMPORARY TABLE tmp_table1;
      END; $$

      delimiter ;


      Usage example (normalization):



      CALL split_value_into_multiple_rows('my_contacts', 'contact_id', 'interests', ',');

      CREATE TABLE interests (
      interest_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      interest VARCHAR(30) NOT NULL
      ) SELECT DISTINCT value interest FROM tmp_table2;

      CREATE TABLE contact_interest (
      contact_id INT NOT NULL,
      interest_id INT NOT NULL,
      CONSTRAINT fk_contact_interest_my_contacts_contact_id FOREIGN KEY (contact_id) REFERENCES my_contacts (contact_id),
      CONSTRAINT fk_contact_interest_interests_interest_id FOREIGN KEY (interest_id) REFERENCES interests (interest_id)
      ) SELECT my_contacts.contact_id, interests.interest_id
      FROM my_contacts, tmp_table2, interests
      WHERE my_contacts.contact_id = tmp_table2.id AND interests.interest = tmp_table2.value;





      share|improve this answer















      My variant: stored procedure that takes table name, field names and delimiter as arguments. Inspired by post http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/



      delimiter $$

      DROP PROCEDURE IF EXISTS split_value_into_multiple_rows $$
      CREATE PROCEDURE split_value_into_multiple_rows(tablename VARCHAR(20),
      id_column VARCHAR(20), value_column VARCHAR(20), delim CHAR(1))
      BEGIN
      DECLARE id INT DEFAULT 0;
      DECLARE value VARCHAR(255);
      DECLARE occurrences INT DEFAULT 0;
      DECLARE i INT DEFAULT 0;
      DECLARE splitted_value VARCHAR(255);
      DECLARE done INT DEFAULT 0;
      DECLARE cur CURSOR FOR SELECT tmp_table1.id, tmp_table1.value FROM
      tmp_table1 WHERE tmp_table1.value IS NOT NULL AND tmp_table1.value != '';
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

      SET @expr = CONCAT('CREATE TEMPORARY TABLE tmp_table1 (id INT NOT NULL, value VARCHAR(255)) ENGINE=Memory SELECT ',
      id_column,' id, ', value_column,' value FROM ',tablename);
      PREPARE stmt FROM @expr;
      EXECUTE stmt;
      DEALLOCATE PREPARE stmt;

      DROP TEMPORARY TABLE IF EXISTS tmp_table2;
      CREATE TEMPORARY TABLE tmp_table2 (id INT NOT NULL, value VARCHAR(255) NOT NULL) ENGINE=Memory;

      OPEN cur;
      read_loop: LOOP
      FETCH cur INTO id, value;
      IF done THEN
      LEAVE read_loop;
      END IF;

      SET occurrences = (SELECT CHAR_LENGTH(value) -
      CHAR_LENGTH(REPLACE(value, delim, '')) + 1);
      SET i=1;
      WHILE i <= occurrences DO
      SET splitted_value = (SELECT TRIM(SUBSTRING_INDEX(
      SUBSTRING_INDEX(value, delim, i), delim, -1)));
      INSERT INTO tmp_table2 VALUES (id, splitted_value);
      SET i = i + 1;
      END WHILE;
      END LOOP;

      SELECT * FROM tmp_table2;
      CLOSE cur;
      DROP TEMPORARY TABLE tmp_table1;
      END; $$

      delimiter ;


      Usage example (normalization):



      CALL split_value_into_multiple_rows('my_contacts', 'contact_id', 'interests', ',');

      CREATE TABLE interests (
      interest_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      interest VARCHAR(30) NOT NULL
      ) SELECT DISTINCT value interest FROM tmp_table2;

      CREATE TABLE contact_interest (
      contact_id INT NOT NULL,
      interest_id INT NOT NULL,
      CONSTRAINT fk_contact_interest_my_contacts_contact_id FOREIGN KEY (contact_id) REFERENCES my_contacts (contact_id),
      CONSTRAINT fk_contact_interest_interests_interest_id FOREIGN KEY (interest_id) REFERENCES interests (interest_id)
      ) SELECT my_contacts.contact_id, interests.interest_id
      FROM my_contacts, tmp_table2, interests
      WHERE my_contacts.contact_id = tmp_table2.id AND interests.interest = tmp_table2.value;






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited May 27 '18 at 18:56









      ashkufaraz

      3,81144166




      3,81144166










      answered Feb 5 '17 at 12:57









      AndreyAndrey

      8911010




      8911010












      • Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

        – raviabhiram
        Feb 22 at 6:29

















      • Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

        – raviabhiram
        Feb 22 at 6:29
















      Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

      – raviabhiram
      Feb 22 at 6:29





      Beautifully written. With a few changes I was able to incorporate this into my database to ensure it is in 1st normal form. Thank you.

      – raviabhiram
      Feb 22 at 6:29











      1














      CREATE PROCEDURE `getVal`()
      BEGIN
      declare r_len integer;
      declare r_id integer;
      declare r_val varchar(20);
      declare i integer;
      DECLARE found_row int(10);
      DECLARE row CURSOR FOR select length(replace(val,"|","")),id,val from split;
      create table x(id int,name varchar(20));
      open row;
      select FOUND_ROWS() into found_row ;
      read_loop: LOOP
      IF found_row = 0 THEN
      LEAVE read_loop;
      END IF;
      set i = 1;
      FETCH row INTO r_len,r_id,r_val;
      label1: LOOP
      IF i <= r_len THEN
      insert into x values( r_id,SUBSTRING(replace(r_val,"|",""),i,1));
      SET i = i + 1;
      ITERATE label1;
      END IF;
      LEAVE label1;
      END LOOP label1;
      set found_row = found_row - 1;
      END LOOP;
      close row;
      select * from x;
      drop table x;
      END





      share|improve this answer



























        1














        CREATE PROCEDURE `getVal`()
        BEGIN
        declare r_len integer;
        declare r_id integer;
        declare r_val varchar(20);
        declare i integer;
        DECLARE found_row int(10);
        DECLARE row CURSOR FOR select length(replace(val,"|","")),id,val from split;
        create table x(id int,name varchar(20));
        open row;
        select FOUND_ROWS() into found_row ;
        read_loop: LOOP
        IF found_row = 0 THEN
        LEAVE read_loop;
        END IF;
        set i = 1;
        FETCH row INTO r_len,r_id,r_val;
        label1: LOOP
        IF i <= r_len THEN
        insert into x values( r_id,SUBSTRING(replace(r_val,"|",""),i,1));
        SET i = i + 1;
        ITERATE label1;
        END IF;
        LEAVE label1;
        END LOOP label1;
        set found_row = found_row - 1;
        END LOOP;
        close row;
        select * from x;
        drop table x;
        END





        share|improve this answer

























          1












          1








          1







          CREATE PROCEDURE `getVal`()
          BEGIN
          declare r_len integer;
          declare r_id integer;
          declare r_val varchar(20);
          declare i integer;
          DECLARE found_row int(10);
          DECLARE row CURSOR FOR select length(replace(val,"|","")),id,val from split;
          create table x(id int,name varchar(20));
          open row;
          select FOUND_ROWS() into found_row ;
          read_loop: LOOP
          IF found_row = 0 THEN
          LEAVE read_loop;
          END IF;
          set i = 1;
          FETCH row INTO r_len,r_id,r_val;
          label1: LOOP
          IF i <= r_len THEN
          insert into x values( r_id,SUBSTRING(replace(r_val,"|",""),i,1));
          SET i = i + 1;
          ITERATE label1;
          END IF;
          LEAVE label1;
          END LOOP label1;
          set found_row = found_row - 1;
          END LOOP;
          close row;
          select * from x;
          drop table x;
          END





          share|improve this answer













          CREATE PROCEDURE `getVal`()
          BEGIN
          declare r_len integer;
          declare r_id integer;
          declare r_val varchar(20);
          declare i integer;
          DECLARE found_row int(10);
          DECLARE row CURSOR FOR select length(replace(val,"|","")),id,val from split;
          create table x(id int,name varchar(20));
          open row;
          select FOUND_ROWS() into found_row ;
          read_loop: LOOP
          IF found_row = 0 THEN
          LEAVE read_loop;
          END IF;
          set i = 1;
          FETCH row INTO r_len,r_id,r_val;
          label1: LOOP
          IF i <= r_len THEN
          insert into x values( r_id,SUBSTRING(replace(r_val,"|",""),i,1));
          SET i = i + 1;
          ITERATE label1;
          END IF;
          LEAVE label1;
          END LOOP label1;
          set found_row = found_row - 1;
          END LOOP;
          close row;
          select * from x;
          drop table x;
          END






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 15 '16 at 8:26









          ImanezImanez

          472513




          472513





















              -1














              Here is my solution



              -- Create the maximum number of words we want to pick (indexes in n)
              with recursive n(i) as (
              select
              1 i
              union all
              select i+1 from n where i < 1000
              )
              select distinct
              s.id,
              s.oaddress,
              -- n.i,
              -- use the index to pick the nth word, the last words will always repeat. Remove the duplicates with distinct
              if(instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' ') > 0,
              reverse(substr(reverse(trim(substring_index(s.oaddress,' ',n.i))),1,
              instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' '))),
              trim(substring_index(s.oaddress,' ',n.i))) oth
              from
              app_schools s,
              n





              share|improve this answer



























                -1














                Here is my solution



                -- Create the maximum number of words we want to pick (indexes in n)
                with recursive n(i) as (
                select
                1 i
                union all
                select i+1 from n where i < 1000
                )
                select distinct
                s.id,
                s.oaddress,
                -- n.i,
                -- use the index to pick the nth word, the last words will always repeat. Remove the duplicates with distinct
                if(instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' ') > 0,
                reverse(substr(reverse(trim(substring_index(s.oaddress,' ',n.i))),1,
                instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' '))),
                trim(substring_index(s.oaddress,' ',n.i))) oth
                from
                app_schools s,
                n





                share|improve this answer

























                  -1












                  -1








                  -1







                  Here is my solution



                  -- Create the maximum number of words we want to pick (indexes in n)
                  with recursive n(i) as (
                  select
                  1 i
                  union all
                  select i+1 from n where i < 1000
                  )
                  select distinct
                  s.id,
                  s.oaddress,
                  -- n.i,
                  -- use the index to pick the nth word, the last words will always repeat. Remove the duplicates with distinct
                  if(instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' ') > 0,
                  reverse(substr(reverse(trim(substring_index(s.oaddress,' ',n.i))),1,
                  instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' '))),
                  trim(substring_index(s.oaddress,' ',n.i))) oth
                  from
                  app_schools s,
                  n





                  share|improve this answer













                  Here is my solution



                  -- Create the maximum number of words we want to pick (indexes in n)
                  with recursive n(i) as (
                  select
                  1 i
                  union all
                  select i+1 from n where i < 1000
                  )
                  select distinct
                  s.id,
                  s.oaddress,
                  -- n.i,
                  -- use the index to pick the nth word, the last words will always repeat. Remove the duplicates with distinct
                  if(instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' ') > 0,
                  reverse(substr(reverse(trim(substring_index(s.oaddress,' ',n.i))),1,
                  instr(reverse(trim(substring_index(s.oaddress,' ',n.i))),' '))),
                  trim(substring_index(s.oaddress,' ',n.i))) oth
                  from
                  app_schools s,
                  n






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 14 '18 at 20:25









                  Tawonga Donnell MsiskaTawonga Donnell Msiska

                  1




                  1



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f17942508%2fsql-split-values-to-multiple-rows%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

                      Darth Vader #20

                      Ondo