简体   繁体   中英

SQL for splitting a single row data into multiple rows based on character

So far I have written a query that splits the first row into multiple rows but the result for the following N rows will be N rows returning null values.

Here is the scenario.

select address from sample;

Which would return following 4 rows,

Stack Overflow# is a# question and# answer site
Stack Overflow# is a# question and# answer site
Stack Overflow# is a# question and# answer site
Stack Overflow# is a# question and# answer site

When tried to split each row into multiple rows using the following query,

with test as (select address as str from sample)
select regexp_substr (str, '[^#]+', 1, rownum) split
from test
connect by level <= length (regexp_substr (str, '[^#]+', 1, rownum)) + 1
;

The following values will be returned.

Stack Overflow
is a
question and
answer site
(null)
(null)
(null)

Why cant I get the results for all rows?

Why cant I get the results for all rows?

There are two things incorrect with your query.

  1. Because the use of ROWNUM is incorrect. You are using the ROWNUM in the same query as a condition, however, the ROWNUM is not yet incremented to next value . so, it's value is just one. So, you just get only 1 row.

  2. You need to do the split for all the rows and not just the first row. You need to loop through all the rows. But, at the same time you should avoid a cyclic-loop and get rid of duplicates.

There are many ways of doing the string split for multiple rows. I have demonstrated in my article here http://lalitkumarb.wordpress.com/2015/03/04/split-comma-delimited-strings-in-a-table-using-oracle-sql/

For example, you could do it like this:

SQL> WITH t AS(
  2  SELECT 'Stack Overflow# is a# question and# answer site' text FROM dual UNION ALL
  3  SELECT 'Stack Overflow# IS a# question and# answer site' text FROM dual UNION ALL
  4  SELECT 'Stack Overflow# is a# question and# answer site' text FROM dual UNION ALL
  5  SELECT 'Stack Overflow# IS a# question and# answer site' text FROM dual
  6  )
  7  SELECT trim(regexp_substr(t.text, '[^#]+', 1, lines.column_value)) text
  8      FROM t,
  9        TABLE (CAST (MULTISET
 10        (SELECT LEVEL FROM dual CONNECT BY LEVEL <= regexp_count(t.text, '#')+1)
 11                     AS sys.odciNumberList
 12                    )
 13              ) lines
 14  /

TEXT
-----------------------------------------------
Stack Overflow
is a
question and
answer site
Stack Overflow
IS a
question and
answer site
Stack Overflow
is a
question and
answer site
Stack Overflow
IS a
question and
answer site

16 rows selected.

SQL>

So, you now get 16 rows . Works perfectly!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM