By user3407090


2015-07-16 20:50:44 8 Comments

I have values being returned with 255 comma separated values. Is there an easy way to split those into columns without having 255 substr?

ROW  | VAL
----------- 
1    | 1.25, 3.87, 2, ... 
2    | 5, 4, 3.3, ....

to

ROW | VAL | VAL | VAL ...
--------------------- 
1   |1.25 |3.87 | 2 ...     
2   | 5   | 4   | 3.3 ...

4 comments

@user9213118 2018-01-13 15:58:44

hierarchical query could be used. pivoting can be done with case and group by.

with value_t as
( 
  select row_t,row_number() OVER (partition by row_t order by rownum )rn,
  regexp_substr(val, '[^,]+', 1, LEVEL) val from Table1
CONNECT BY LEVEL <= regexp_count(val, '[^,]+') 
AND prior row_t = row_t 
AND prior sys_guid() is not null
  ) select row_t, max( case when rn = 1 THEN val end ) val_1,
  max( case when rn = 2 THEN val end ) val_2,
  max( case when rn = 3 THEN val end ) val_3
  from value_t
  group by row_t;

@J. Chomel 2017-04-12 07:43:39

If you only have one row, and time to create your


select * from (
  select rownum r , collection.*  
    from TABLE(cto_table(',','1.25, 3.87, 2, 19,, 1, 9, ')) collection
)
PIVOT ( 
  LISTAGG(column_value) within group (order by 1) as val 
  for r in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
)

FYI: here is how to create the cto_table function:

CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);
CREATE OR REPLACE
FUNCTION cto_table(p_sep in Varchar2, p_list IN VARCHAR2)
  RETURN t_my_list
AS
  l_string VARCHAR2(32767) := p_list || p_sep;
  l_sep_index PLS_INTEGER;
  l_index PLS_INTEGER := 1;
  l_tab t_my_list     := t_my_list();
BEGIN
  LOOP
    l_sep_index := INSTR(l_string, p_sep, l_index);
    EXIT
  WHEN l_sep_index = 0;
    l_tab.EXTEND;
    l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_sep_index - l_index));
    l_index            := l_sep_index + 1;
  END LOOP;
  RETURN l_tab;
END cto_table;
/

@Gary_W 2015-07-16 21:17:55

Beware! The regexp_substr expression of the format '[^,]+' will not return the expected value if there is a null element in the list and you want that item or one after it. Consider this example where the 4th element is NULL and I want the 5th element and thus expect the '5' to be returned:

SQL> select regexp_substr('1,2,3,,5,6', '[^,]+', 1, 5) from dual;

R
-
6

Surprise! It returns the 5th NON-NULL element, not the actual 5th element! Incorrect data returned and you may not even catch it. Try this instead:

SQL> select regexp_substr('1,2,3,,5,6', '(.*?)(,|$)', 1, 5, NULL, 1) from dual;

R
-
5

So, the above corrected REGEXP_SUBSTR says to look for the 5th occurrence of 0 or more comma-delimited characters followed by a comma or the end of the line (allows for the next separator, be it a comma or the end of the line) and when found return the 1st subgroup (the data NOT including the comma or end of the line).

The search match pattern '(.*?)(,|$)' explained:

(             = Start a group
.             = match any character
*             = 0 or more matches of the preceding character
?             = Match 0 or 1 occurrences of the preceding pattern
)             = End the 1st group
(             = Start a new group (also used for logical OR)
,             = comma
|             = OR
$             = End of the line
)             = End the 2nd group

EDIT: More info added and simplified the regex.

See this post for more info and a suggestion to encapsulate this in a function for easy reuse: REGEX to select nth value from a list, allowing for nulls It's the post where I discovered the format '[^,]+' has the problem. Unfortunately it's the regex format you will most commonly see as the answer for questions regarding how to parse a list. I shudder to think of all the incorrect data being returned by '[^,]+'!

@Gordon Linoff 2015-07-16 20:59:39

You can use regexp_substr():

select regexp_substr(val, '[^,]+', 1, 1) as val1, 
       regexp_substr(val, '[^,]+', 1, 2) as val2, 
       regexp_substr(val, '[^,]+', 1, 3) as val3, 
       . . .

I would suggest that you generate a column of 255 numbers in Excel (or another spreadsheet), and use the spreadsheet to generate the SQL code.

@Wouter 2015-08-14 11:39:11

This is not a correct answer, as the question explicitly states "without having 255 substr". Also, mind the Answer of Gary_W, it is a -very- valid concern.

@Gordon Linoff 2015-08-14 12:50:46

@Wouter . . . The point of the answer was to generate the values in a spreadsheet.

@Wouter 2015-08-14 14:09:18

Yes; clever. But still not an answer to the question at hand.

Related Questions

Sponsored Content

14 Answered Questions

[SOLVED] Turning a Comma Separated string into individual rows

25 Answered Questions

[SOLVED] Finding duplicate values in a SQL table

  • 2010-04-07 18:17:29
  • Alex
  • 2242605 View
  • 1524 Score
  • 25 Answer
  • Tags:   sql duplicates

57 Answered Questions

[SOLVED] How do you split a list into evenly sized chunks?

7 Answered Questions

37 Answered Questions

19 Answered Questions

[SOLVED] Get list of all tables in Oracle?

  • 2008-10-15 17:54:49
  • vitule
  • 2002941 View
  • 1001 Score
  • 19 Answer
  • Tags:   sql oracle

4 Answered Questions

[SOLVED] Split comma-separated strings in a column into separate rows

  • 2012-12-08 02:13:44
  • RoyalTS
  • 22406 View
  • 78 Score
  • 4 Answer
  • Tags:   r string split r-faq

1 Answered Questions

[SOLVED] split comma separated values into columns dynamically

3 Answered Questions

[SOLVED] Split comma separated column data into additional columns

6 Answered Questions

[SOLVED] oracle -- Split multiple comma separated values in oracle table to multiple rows

Sponsored Content