1. 程式人生 > 資料庫 >ORACLE逗號分割的字串轉多行(轉載)

ORACLE逗號分割的字串轉多行(轉載)

分割單行資料

我們需要使用REGEXP_SUBSTRREGEXP_COUNT兩個ORACLE函式

function REGEXP_SUBSTR(string, pattern, position, occurrence, modifier)
string:需要進行正則處理的字串
pattern:進行匹配的正則表示式
position:起始位置,從第幾個字元開始正則表示式匹配(預設為1)
occurrence:標識第幾個匹配組,預設為1
modifier:模式(‘i’不區分大小寫進行檢索;‘c’區分大小寫進行檢索。預設為’c’)

function REGEXP_COUNT ( string, pattern [, position [, match_param]])


返回pattern 在string串中出現的次數。如果未找到匹配,則函式返回0。position 變數告訴Oracle 在源串的什麼位置開始搜尋。在開始位置之後每出現一次模式,都會使計數結果增加1。

SELECT REGEXP_SUBSTR('B00053,D00058,D00094', '[^,]+', 1, LEVEL) VALUE
  FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT('B00053,D00058,D00094', '[^,]+')
  • 1
  • 2
  • 3

分割後結果如下:
在這裡插入圖片描述

分割多行資料

我們有三行初始資料
在這裡插入圖片描述

WITH TEMP AS
 (SELECT T.VALUE, T.COUNTS, T.EXE_ID
    FROM SC_MONIT_EXERESULT T
   INNER JOIN SYS_TASK_EXECUTE A
      ON T.EXE_ID = A.EXEC_ID
   WHERE FIELD_CODE = 'fundList'
     AND A.BUSIDATE = '20180604'
     AND VALUE = 'B00053,D00058,D00094')
SELECT REGEXP_SUBSTR(VALUE, '[^,]+', 1, LEVEL) VALUE,
       COUNTS,
       EXE_ID
  FROM TEMP
CONNECT BY LEVEL <= REGEXP_COUNT(VALUE, '[^,]+')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

分割後資料變成了39行而不是9行!
問題出在使用connect by時,沒有類似 id=prior pid的條件,而是 connect by rownum<xxx 或 connect by level<xxx 時,每一條記錄都會作為自己或者其他記錄的子節點,也就說,每一條記錄的子節點就是表上所有的記錄。而樹的層數就是rownum(或是level)值。
假設表中有N條記錄,則記F(N,l)為select id,level from t connect by level<l 的結果集數目。那麼:
F ( N , 1 ) = N F(N,1)=NF(N,1)=N

F ( N , l ) = F ( N , l − 1 ) ∗ N + N F(N,l) = F(N,l-1)*N+NF(N,l)=F(N,l−1)∗N+N
l e v e l &lt; = 3 level&lt;=3level<=3 時,遞迴查詢到的樹狀結構:
在這裡插入圖片描述

我們需要給樹加上父子關係,用rownum作為PK列

WITH TEMP AS
 (SELECT T.VALUE, T.COUNTS, T.EXE_ID, ROWNUM ROWNUM1
    FROM SC_MONIT_EXERESULT T
   INNER JOIN SYS_TASK_EXECUTE A
      ON T.EXE_ID = A.EXEC_ID
   WHERE FIELD_CODE = 'fundList'
     AND A.BUSIDATE = '20180604'
     AND VALUE = 'B00053,D00058,D00094')
SELECT 'fundCode' FIELD_CODE,
       REGEXP_SUBSTR(VALUE, '[^,]+', 1, LEVEL) VALUE,
       COUNTS,
       EXE_ID
  FROM TEMP
CONNECT BY PRIOR ROWNUM1 = ROWNUM1
       AND LEVEL <= REGEXP_COUNT(VALUE, '[^,]+')
       AND PRIOR DBMS_RANDOM.VALUE() IS NOT NULL
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

PRIOR DBMS_RANDOM.VALUE() IS NOT NULL告訴ORACLE每次迴圈是不一樣的,不然會報connect by死迴圈
最後得到的結果:
在這裡插入圖片描述