Oracle處理以,隔開存儲的數據

,隔開的字符串。我們需要管理這個字符串,使其中包含某個測點標識的數據去掉,你會如何做呢(思考一會)?

一開始想到的是字符串替換,後面發現這種方式不好,有異常情況發生(某個測點標識包含另一個測點標識時會發生異常),而且要考慮的情況比較多。

這種方式不行,那更好的方式是什麼?

從數據存儲的結構上來看,我們最好的存儲方式是一個測點標識一條記錄,這樣就可以區分開了,既然這樣我們如何將數據分割開來呢?

一個一個找?是的,其實就是這樣。

:a,b,c,d

首先找到a,接着找到b,依次下去找到最後一個d

首先分析數據的結構(多種角度):

1a 第一個逗號 b 第二個逗號 c 第三個逗號 d

2非逗號 逗號非逗號逗號非逗號非逗號

3第一個非逗號 逗號第二個非逗號逗號第三個非逗號逗號第四個非逗號

。。。。

數據始終是有規律的,數據有兩個格式:逗號和非逗號,同時它們都有位置信息。

我們可以結合這個信息找到其中的信息。

Oracle中有個函數:

function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)

__srcstr     :需要進行正則處理的字符串

__pattern    :進行匹配的正則表達式

__position   :起始位置,從第幾個字符開始正則表達式匹配(默認爲1

__occurrence :標識第幾個匹配組,默認爲1

__modifier   :模式('i'不區分大小寫進行檢索;'c'區分大小寫進行檢索。默認爲'c'。)

其中的patternoccurrence是這個問題求解的關鍵所在。

模擬這個過程:

SELECT REGEXP_SUBSTR('a,b,c,d','[^,]+',1,1)AS STRFROM DUAL;  

SELECT REGEXP_SUBSTR('a,b,c,d','[^,]+',1,2)AS STRFROM DUAL;

SELECT REGEXP_SUBSTR('a,b,c,d','[^,]+',1,3)AS STRFROM DUAL;  

SELECT REGEXP_SUBSTR('a,b,c,d','[^,]+',1,4)AS STRFROM DUAL;

 

上面這些sql,唯一不同的就是匹配的是第幾個匹配組。

那我們能不能通過輔助表產生這些遞增的匹配組索引信息,當然能

SELECT LEVEL FROM DUAL CONNECT BY LEVEL <=7;  

產生1-7的遞增索引,結合上面的例子來做

 

這樣會有額外的空數據,那麼我們需要確定到底有少個逗號

LENGTH('a,b,c,d')-LENGTH(REPLACE('a,b,c,d',',',''))+1

 

結合到我們的業務上,需要移除指定測點標識的數據,先拆分成多行,再通過指定的測點標識進行過濾,最後通過wm_concat函數重組剩下滿足的測點標識

SELECT  WM_CONCAT(PJCDDM) AS PJCDDM

   FROM  

   (SELECT SUBDY.XH,REGEXP_SUBSTR(SUBDY.PJCDDM,'[^,]+',1,L) AS  PJCDDM,  

       FROM T_JCSJZX_PJFW_DBSDY SUBDY,  

       (SELECT LEVEL L FROM DUAL CONNECT BY LEVEL<=150)  

          WHERE L<=LENGTH(SUBDY.PJCDDM) -LENGTH(REPLACE(SUBDY.PJCDDM,','))+1                ORDER BY SUBDY.PJCDDM  

      ) DY WHERE DY.PJCDDM !=  過濾的測點 AND DY_MAIN.XH = DY.XH GROUP BY DY.XH  

 

注:mysql中同樣的思路只是查找數據的函數(substring_index)稍有不同而已

 

最終sql:

UPDATE T_JCSJZX_PJFW_DBSDY DY_MAIN SET(PJCDDM,PJCDMC) = (

       SELECT  WM_CONCAT(PJCDDM) AS PJCDDM, WM_CONCAT(PJCDMC) AS PJCDMC

       FROM

       (SELECT SUBDY.XH,REGEXP_SUBSTR(SUBDY.PJCDDM,'[^,]+',1,L) AS  PJCDDM,

               REGEXP_SUBSTR(SUBDY.PJCDMC,'[^,]+',1,L) AS  PJCDMC

               FROM T_JCSJZX_PJFW_DBSDY SUBDY,

               (SELECT LEVEL L FROM DUAL CONNECT BY LEVEL<=150)

               WHERE L<=LENGTH(SUBDY.PJCDDM) -LENGTH(REPLACE(SUBDY.PJCDDM,','))+1

               ORDER BY SUBDY.PJCDDM,SUBDY.PJCDMC

        ) DY WHERE DY.PJCDDM != '530700FB2501000201' AND DY_MAIN.XH = DY.XH GROUP BY DY.XH

) WHERE INSTR(','||DY_MAIN.PJCDDM||',', ','||'530700FB2501000201'||',') > 0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章