以,隔開的字符串。我們需要管理這個字符串,使其中包含某個測點標識的數據去掉,你會如何做呢(思考一會)?
一開始想到的是字符串替換,後面發現這種方式不好,有異常情況發生(某個測點標識包含另一個測點標識時會發生異常),而且要考慮的情況比較多。
這種方式不行,那更好的方式是什麼?
從數據存儲的結構上來看,我們最好的存儲方式是一個測點標識一條記錄,這樣就可以區分開了,既然這樣我們如何將數據分割開來呢?
一個一個找?是的,其實就是這樣。
例:a,b,c,d
首先找到a,接着找到b,依次下去找到最後一個d
首先分析數據的結構(多種角度):
1、a 第一個逗號 b 第二個逗號 c 第三個逗號 d
2、非逗號 逗號非逗號逗號非逗號非逗號
3、第一個非逗號 逗號第二個非逗號逗號第三個非逗號逗號第四個非逗號
。。。。
數據始終是有規律的,數據有兩個格式:逗號和非逗號,同時它們都有位置信息。
我們可以結合這個信息找到其中的信息。
Oracle中有個函數:
function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)
__srcstr :需要進行正則處理的字符串
__pattern :進行匹配的正則表達式
__position :起始位置,從第幾個字符開始正則表達式匹配(默認爲1)
__occurrence :標識第幾個匹配組,默認爲1
__modifier :模式('i'不區分大小寫進行檢索;'c'區分大小寫進行檢索。默認爲'c'。)
其中的pattern和occurrence是這個問題求解的關鍵所在。
模擬這個過程:
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