分为行和列Oracle

时间:2017-11-23 20:12:03

标签: oracle function split pivot regexp-substr

我正在创建一个函数,它根据链的分割返回一个表类型对象,查询如下:

WITH COLUMNA AS (
    SELECT ROWNUM COL_ID, REGEXP_SUBSTR ('A,B,C:D,E,F:','[^:]+',1,LEVEL) COL FROM DUAL
    CONNECT BY REGEXP_SUBSTR ('A,B,C:D,E,F:','[^:]+',1,LEVEL) IS NOT NULL
    ORDER BY COL_ID
)
SELECT * FROM (SELECT COL_ID, ROWNUM FIL_ID, SUBSTR(COL, INSTR(COL, ',', 1, LVL) + 1, INSTR(COL, ',', 1, LVL + 1) - INSTR(COL, ',', 1, LVL) - 1) NAME 
FROM
( SELECT ',' || COL || ',' AS COL, COL_ID FROM COLUMNA ),
( SELECT LEVEL AS LVL FROM DUAL CONNECT BY LEVEL <= 100 )
WHERE LVL <= LENGTH(COL) - LENGTH(REPLACE(COL, ',')) - 1
ORDER BY COL_ID, NAME
) FILA

结果如下:

COL_ID FIL_ID NAME
1       1       A
1       2       B
1       3       C
2       4       D
2       5       E
2       6       F

我需要获得以下结果

COL_ID VAL1    VAL2   VAL3   VALN
1       A       B      C      X
2       D       E      F      Y

我希望你的宝贵帮助!!!

1 个答案:

答案 0 :(得分:0)

您的对象中需要有固定数量的列:

CREATE TYPE values_obj AS OBJECT(
  COL_id INTEGER,
  VAL1   VARCHAR2(10),
  VAL2   VARCHAR2(10),
  VAL3   VARCHAR2(10),
  VAL4   VARCHAR2(10),
  VAL5   VARCHAR2(10)
)
/

CREATE TYPE values_tab AS TABLE OF values_obj
/

CREATE OR REPLACE FUNCTION split_values(
  in_list VARCHAR2
) RETURN values_tab
IS
  vals VALUES_TAB;
BEGIN
  SELECT values_obj(
           LEVEL,
           REGEXP_SUBSTR( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)', 1, LEVEL, NULL, 1 ),
           REGEXP_SUBSTR( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)', 1, LEVEL, NULL, 2 ),
           REGEXP_SUBSTR( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)', 1, LEVEL, NULL, 3 ),
           REGEXP_SUBSTR( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)', 1, LEVEL, NULL, 4 ),
           REGEXP_SUBSTR( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)', 1, LEVEL, NULL, 5 )
         )
  BULK COLLECT INTO vals
  FROM   DUAL
  CONNECT BY LEVEL < REGEXP_COUNT( in_list, '([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*),?([^:,]*).*?(:|$)' );

  RETURN vals;
END;
/

然后你可以这样做:

SELECT *
FROM   TABLE( split_values( 'A,B,C:D,E,F,G:H,I,J,K,L,M::N' ) );

哪个输出:

COL_ID  VAL1    VAL2    VAL3    VAL4    VAL5
------  ----    ----    ----    ----    ----
     1     A       B       C       -       - 
     2     D       E       F       G       - 
     3     H       I       J       K       L
     4     -       -       -       -       - 
     5     N       -       -       -       -