Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split comma separated values of a column in row, through Oracle SQL query

I have a table like below:

-------------
ID   | NAME
-------------
1001 | A,B,C
1002 | D,E,F
1003 | C,E,G
-------------

I want these values to be displayed as:

-------------
ID   | NAME
-------------
1001 | A
1001 | B
1001 | C
1002 | D
1002 | E
1002 | F
1003 | C
1003 | E
1003 | G
-------------

I tried doing:

select split('A,B,C,D,E,F', ',') from dual; -- WILL RETURN COLLECTION

select column_value
from table (select split('A,B,C,D,E,F', ',') from dual); -- RETURN COLUMN_VALUE
like image 741
vipin.huddar Avatar asked May 14 '14 08:05

vipin.huddar


People also ask

How split comma separated column values in SQL?

Split comma-separated value string in a column. SELECT ProductId, Name, value FROM Product CROSS APPLY STRING_SPLIT(Tags, ','); Here is the result set. The order of the output may vary as the order is not guaranteed to match the order of the substrings in the input string.

How do you turn a comma separated string into a row?

The tabular function will return the result set in a row-column format from the comma-separated string. Recent versions of SQL Server provide a built-in function string_split() to do the same task with the input parameters of the input string and delimiter.


2 Answers

There are multiple options. See Split comma delimited strings in a table in Oracle.

Using REGEXP_SUBSTR:

SQL> WITH sample_data AS(
  2  SELECT 10001 ID, 'A,B,C' str FROM dual UNION ALL
  3  SELECT 10002 ID, 'D,E,F' str FROM dual UNION ALL
  4  SELECT 10003 ID, 'C,E,G' str FROM dual
  5  )
  6  -- end of sample_data mimicking real table
  7  SELECT distinct id, trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
  8  FROM sample_data
  9  CONNECT BY LEVEL <= regexp_count(str, ',')+1
 10  ORDER BY ID
 11  /

        ID STR
---------- -----
     10001 A
     10001 B
     10001 C
     10002 D
     10002 E
     10002 F
     10003 C
     10003 E
     10003 G

9 rows selected.

SQL>

Using XMLTABLE:

SQL> WITH sample_data AS(
  2  SELECT 10001 ID, 'A,B,C' str FROM dual UNION ALL
  3  SELECT 10002 ID, 'D,E,F' str FROM dual UNION ALL
  4  SELECT 10003 ID, 'C,E,G' str FROM dual
  5  )
  6  -- end of sample_data mimicking real table
  7  SELECT id,
  8        trim(COLUMN_VALUE) str
  9  FROM sample_data,
 10       xmltable(('"'
 11          || REPLACE(str, ',', '","')
 12          || '"'))
 13  /

        ID STR
---------- ---
     10001 A
     10001 B
     10001 C
     10002 D
     10002 E
     10002 F
     10003 C
     10003 E
     10003 G

9 rows selected.
like image 148
Lalit Kumar B Avatar answered Oct 09 '22 19:10

Lalit Kumar B


Try using below query:

 WITH T AS (SELECT 'A,B,C,D,E,F' STR  FROM DUAL)   SELECT    
 REGEXP_SUBSTR (STR, '[^,]+', 1, LEVEL) SPLIT_VALUES  FROM T 
 CONNECT BY LEVEL <= (SELECT LENGTH (REPLACE (STR, ',', NULL)) FROM T)

Below Query with ID:

WITH TAB AS 
(SELECT '1001' ID, 'A,B,C,D,E,F' STR FROM DUAL
)
SELECT    ID, 
REGEXP_SUBSTR (STR, '[^,]+', 1, LEVEL) SPLIT_VALUES  FROM TAB 
CONNECT BY LEVEL <= (SELECT LENGTH (REPLACE (STR, ',', NULL)) FROM TAB);

EDIT: Try using below query for multiple IDs and multiple separation:

WITH TAB AS 
(SELECT '1001' ID, 'A,B,C,D,E,F' STR FROM DUAL
UNION
SELECT '1002' ID, 'D,E,F' STR FROM DUAL
UNION
SELECT '1003' ID, 'C,E,G' STR FROM DUAL
)
select id, substr(STR, instr(STR, ',', 1, lvl) + 1, instr(STR, ',', 1, lvl + 1) - instr(STR, ',', 1, lvl) - 1) name 
from
( select ',' || STR || ',' as STR, id from TAB ),
( select level as lvl from dual connect by level <= 100 )
where lvl <= length(STR) - length(replace(STR, ',')) - 1

order by ID, NAME
like image 34
Nishanthi Grashia Avatar answered Oct 09 '22 18:10

Nishanthi Grashia