Oracle查詢優化-使用字符串

--1.遍歷字符串
--1.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT '每天向上' AS 漢字,'TTXS' AS 首拼 FROM DUAL;
--要求每一個漢字對應相應的首拼字母顯示
SELECT SUBSTR(漢字,LEVEL,1) 漢字,SUBSTR(首拼,LEVEL,1) 首拼,LEVEL
FROM V
CONNECT BY LEVEL <=4;
/*總結:CONNECT BY是樹形查詢的一個子句,後面的LEVEL是一個「僞列」,表示樹形中的級別層次,經過LEVEL<=?循環?次,就造成?行數據,LEVEL以1爲步長遞增*/
--2.字符串文字中包含引號
SELECT 'I''M MR.YAN' PROFILE FROM DUAL;
SELECT NQ'[I'M MR.YAN']' PROFILE FROM DUAL;
SELECT NQ'{I'M MR.YAN'}' PROFILE FROM DUAL;
SELECT NQ'(I'M MR.YAN')' PROFILE FROM DUAL;
SELECT Q'<I'M MR.YAN>' PROFILE FROM DUAL;
/*總結:
 *1.在SQL中,'能夠使用兩個'來表達;
 *2.使用q-quoet特性:Q'{***}',***是所要輸入的內容,若是其中包含單引號,那麼單句執行能夠正常顯示,兩個以上合併執行就會報錯;
 *3.使用NQ'{***'}'能夠消除界定符}前面的',其實能夠消除}前的任一單字符,這裏是爲了中和單數'所帶來的的語法錯誤*/
--3.計算字符在字符串中出現的次數
--3.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT 'A,B,C' AS STRS FROM DUAL;
--3.2.ORACLE 11G新函數REGEXP_COUNT
SELECT REGEXP_COUNT(STRS,',')+1 AS CNT FROM V;
--3.3.使用REGEXP_REPLACE
SELECT LENGTH(REGEXP_REPLACE(STRS,'[^,]'))+1 AS CNT FROM V;
/*^表明否認的意思*/
--3.4使用TRANSLATE
SELECT LENGTH(TRANSLATE(STRS,','||STRS,','))+1 AS CNT FROM V;
--3.5.若是分隔符長度大於1,使用3.4的語句則有誤
CREATE OR REPLACE VIEW V AS
SELECT 'A$%B$%C' AS STRS FROM DUAL;
--錯誤
SELECT LENGTH(TRANSLATE(STRS,'$%'||STRS,'$%'))+1 AS CNT FROM V;
--正確
SELECT LENGTH(TRANSLATE(STRS,'$%'||STRS,'$%'))/LENGTH('$%')+1 AS CNT FROM V;
--推薦
SELECT REGEXP_COUNT(STRS,'\$%')+1 AS CNT FROM V;
--4.刪除指定字符,如C和E
SELECT TRANSLATE('ABCDE','1'||'CE','1')AS STR FROM DUAL; 
SELECT REGEXP_REPLACE('ABCDE','[CE]')AS STR FROM DUAL; 
--5.區隔字母和數字
SELECT REGEXP_REPLACE('A1B2C3','[0-9]','') AS STR,REGEXP_REPLACE('A1B2C3','[^0-9]','') AS NUM FROM DUAL;
SELECT TRANSLATE('A1B2C3',' 0123456789',' ') AS STR,TRANSLATE('A1B2C3','0123456789'||'A1B2C3','0123456789') AS NUM FROM DUAL;
--6.查詢只包含字母或數字型的數據
--6.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT '123' AS DATA FROM DUAL UNION ALL
SELECT 'ABC' FROM DUAL UNION ALL
SELECT 'ABC123' FROM DUAL UNION ALL
SELECT '123ABC' FROM DUAL UNION ALL
SELECT 'A1B2C3' FROM DUAL UNION ALL
SELECT '123ABC$#' FROM DUAL UNION ALL
SELECT '123$' FROM DUAL UNION ALL
SELECT 'A 5' FROM DUAL;
--6.2.使用正則表達式
SELECT DATA FROM V WHERE REGEXP_LIKE(DATA,'^[0-9A-Za-z]+$');
/*^不在方括號裏時表示字符串開始,$表示字符串結束,+表示重複1次以上*/
--也能夠使用*來代替+,*表示重複0次以上,也就是說比上一句多了一個判斷條件:...OR LIKE ''...
SELECT DATA FROM V WHERE REGEXP_LIKE(DATA,'^[0-9A-Za-z]*$');
--與上一句效果同樣,可見... OR LIKE ''並不影響結果,他實際不返回值
SELECT ENAME FROM EMP WHERE EMPNO LIKE '';
--7.提取姓名的大寫首字母縮寫
CREATE OR REPLACE VIEW V AS
SELECT 'Micheal Jackson' AS AL FROM DUAL;
SELECT REGEXP_REPLACE (V.AL,'([[:upper:]])(.*)([[:upper:]])(.*)','\1.\3') AS SX FROM V;
--8.根據表中的行建立一個分隔列
--8.1.WM_CONCAT(版本11.2之前返回值爲VARCHAR,後面變爲CLOB)
SELECT DEPTNO,SUM(SAL) AS TOTAL_SAL,WMSYS.WM_CONCAT(ENAME) AS TOTAL_ENAME FROM EMP GROUP BY DEPTNO;
--8.2.LISTAGG(src,'分隔符') WITHIN GROUP()
SELECT DEPTNO,SUM(SAL) AS TOTAL_SAL,LISTAGG(ENAME,',') WITHIN GROUP(ORDER BY ENAME) AS TOTAL_ENAME FROM EMP GROUP BY DEPTNO;
--9.提取第N個分隔的子串
--9.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT WM_CONCAT(ENAME) AS NAME FROM EMP WHERE DEPTNO IN ('10','20') GROUP BY DEPTNO;
SELECT * FROM V;
NAME
--------------------------------------------------------------------------------
CLARK,KING,MILLER
SMITH,ADAMS,FORD,SCOTT,JONES
--9.2.提取第二個名字,也就是KING和ADAMS
SELECT REGEXP_SUBSTR(V.NAME,'[^,]+',1,2) AS SUBSTR FROM V;
/**
 *1.參數2:「^"在方括號裏表示否,+表示匹配1次以上,'[^,]+'表示匹配不包含逗號的多個字符,也就是各個子串
 *2.參數3:1表示從第一個字符開始
 *3.參數4:2表示第二個能匹配'[^,]+'的字符串,也就是KING和ADAMS
 */
--10.分解IP地址
--10.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT '192.168.0.66' AS IP FROM DUAL;
--10.2.分拆,由於IP中.的個數固定爲3,因此不用加判斷
SELECT REGEXP_SUBSTR(V.IP,'[^.]+',1,LEVEL) AS SUB_IP
FROM V
CONNECT BY LEVEL <=4;
--或直接轉置爲行
SELECT 
REGEXP_SUBSTR(V.IP,'[^.]+',1,1) AS A,
REGEXP_SUBSTR(V.IP,'[^.]+',1,2) AS B,
REGEXP_SUBSTR(V.IP,'[^.]+',1,3) AS C,
REGEXP_SUBSTR(V.IP,'[^.]+',1,4) AS D
FROM V;
--11.將分隔數據轉換爲多值IN列表
--11.1.創建測試視圖
CREATE OR REPLACE VIEW V AS
SELECT 'YAN,WEI,TIAN' AS LOVE FROM DUAL;
--11.2.使用REGEXP_SUBSTR和LEVEL配合
SELECT REGEXP_SUBSTR(V.LOVE,'[^,]+',1,LEVEL) AS SUB_LOVE
FROM V
CONNECT BY LEVEL <=(SELECT LENGTH(TRANSLATE(LOVE,','||LOVE,','))+1 FROM V);
--12.按字母順序排列字符串
--12.1.拆分
VAR V_ENAME VARCHAR2(50);
EXEC :V_ENAME := 'ADAMS';
SELECT :V_ENAME AS ENAME ,SUBSTR(:V_ENAME,LEVEL,1) AS C FROM DUAL
CONNECT BY LEVEL <= LENGTH(:V_ENAME);
--12.2.合併
SELECT ENAME,
  (
  SELECT LISTAGG(SUBSTR(ENAME,LEVEL,1),'') WITHIN GROUP (ORDER BY (SUBSTR(ENAME,LEVEL,1)) ASC) 
  FROM DUAL 
  CONNECT BY LEVEL<=LENGTH(ENAME)
  ) 
  AS NEW_NAME
FROM EMP;
--12.3.去重
SELECT ENAME,
       (
       SELECT LISTAGG(MIN(SUBSTR(ENAME,LEVEL,1)),'') WITHIN GROUP (ORDER BY MIN(SUBSTR(ENAME,LEVEL,1)) ASC) 
       FROM DUAL 
       CONNECT BY LEVEL<=LENGTH(ENAME) 
       GROUP BY SUBSTR(ENAME,LEVEL,1)
       ) 
       AS NEW_NAME
FROM EMP;
                         
相關文章
相關標籤/搜索