如何将多列中的数据分离并解析为单独的行(Oracle)

时间:2017-10-31 16:23:04

标签: sql oracle plsql oracle11g

我的列中包含多个值,每个列和行都用逗号分隔。我试图将它们分成不同的行。如果我有一个空值(如下所示),只要该特定行仍然存在其他值之一,我仍将包含空值。

我给出了什么

First_Name (John,  ,Phil)
Last_Name  (Smith,No, ) 
Location  (CA,GA,NY)

我想要什么

(John, Smith, CA)
( , No, GA)
(Phil, ,NY)

我已尝试使用regexp_substr方法,但它没有返回上面列出的3列中任何一列中都为空的任何行。

2 个答案:

答案 0 :(得分:1)

你可以尝试这样的事情。

SET SERVEROUTPUT ON;
DECLARE 

TYPE etype IS TABLE OF VARCHAR2(100);
erec etype;
BEGIN

 for rec IN  ( SELECT first_name,last_name,location FROM Table1 )
 LOOP

 WITH fname
     AS (SELECT LEVEL   lvl,
                REGEXP_SUBSTR(rec.first_name, '[^,]+', 1, LEVEL)First_name
         FROM   DUAL
         CONNECT BY REGEXP_SUBSTR(rec.first_name, '[^,]+', 1, LEVEL) IS NOT NULL),
     lname
     AS (SELECT LEVEL lvl,
                REGEXP_SUBSTR(rec.last_name, '[^,]+', 1, LEVEL)Last_Name
         FROM   DUAL
         CONNECT BY REGEXP_SUBSTR(rec.last_name, '[^,]+', 1, LEVEL) IS NOT NULL),
     loc
     AS (SELECT LEVEL lvl,
                REGEXP_SUBSTR(rec.location, '[^,]+', 1, LEVEL)Location
         FROM   DUAL
         CONNECT BY REGEXP_SUBSTR(rec.location, '[^,]+', 1, LEVEL) IS NOT NULL)
SELECT first_name
       ||','
       || last_name
       ||','
       || location  BULK COLLECT INTO erec 
FROM   fname fn
       FULL OUTER join lname ln
                    ON fn.lvl = ln.lvl
       FULL OUTER join loc lo
                    ON ln.lvl = lo.lvl;  

FOR i IN 1..erec.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(erec(i));  
END LOOP;

END LOOP;     

END;
/

答案 1 :(得分:1)

with
  inputs ( id, first_name, last_name, location ) as (
    select 101, 'John,,Phil' , 'Smith,No,'   , 'CA,GA,NY' from dual union all
    select 102, 'Jo,Al,Ed,Li', 'Ng,Tso,,Roth', ',ZZ,,BB'  from dual 
  )
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select id,
       regexp_substr(first_name, '([^,]*)(,|$)', 1, level, null, 1) as first_name,
       regexp_substr(last_name , '([^,]*)(,|$)', 1, level, null, 1) as last_name,
       regexp_substr(location  , '([^,]*)(,|$)', 1, level, null, 1) as location
from   inputs
connect by level <= regexp_count(first_name, ',') + 1
       and prior id = id
       and prior sys_guid() is not null
;

  ID FIRST_NAME  LAST_NAME    LOCATION
---- ----------- ------------ --------
 101 John        Smith        CA      
 101             No           GA      
 101 Phil                     NY      
 102 Jo          Ng                   
 102 Al          Tso          ZZ      
 102 Ed                               
 102 Li          Roth         BB