赞
踩
listagg函数拼接字符串后,去重
简单描述一下需求:
有一个员工基本信息表,因为部分员工的存在身兼数职位的情况,也就有多个部门,不同的部门的办公地点可能一样,也可能不一样。这个时候需要把同一个员工的部门拼接起来,把地区也拼接起来,就像这样
员工编号 所属部门 办公地点
922 业务部、财务部 北京、上海
923 业务部、法规部 北京、北京
这时间出现的问题就是需要去重
但是在存储过程中 listagg以及wm_concat都不能用distinct,本来打算用正则表达式(regexp_replace),但是发现一个问题就是,会把’北京、北京西城区’,变成’北京西城区’,也就是’北京西城区’前面的两个字符‘北京’被当成跟第一个‘北京’是相同的。网上也没有啥快捷的方法,所以写了一个函数
CREATE OR REPLACE FUNCTION FUN_LIS_DIST(IN_STR IN VARCHAR2,DLMT IN VARCHAR2) RETURN VARCHAR2 IS /*************************************************************************************************** 英文名称: FUN_LIS_DIST 中文名称: 行转列去重 功 能: 用于去除字符串中重复出现的子字符串,且保持顺序不变,须指定分隔符 例:'1,12,3,12',分隔符为',' 输出的结果为'1,12,3' 入 参:IN_STR in varchar2 -- 字符串:待去重的字符串 DLMT in varchar2 -- 字符串:分隔符 出 参: out varchar2, -- 去重后的字符串 创 建 者: klj 描 述: 版 本: 20200404 add by klj: 新增 ***************************************************************************************************/ /**** 第一步:将输入的字符串按分隔符拆分 例:'1,2,3,2' 拆分为 1 2 3 2 ***/ CURSOR CUR_STR IS SELECT REGEXP_SUBSTR(IN_STR, '[^'||DLMT||']+', 1, ROWNUM) AS STR FROM DUAL CONNECT BY ROWNUM <= (LENGTH(IN_STR) - LENGTH(REGEXP_REPLACE(IN_STR, DLMT, '')) + 1) ; RESULT VARCHAR2(10000); --输出的字符串 LEN_DLMT NUMBER ; --分隔符的长度 BEGIN IF INSTR(IN_STR,DLMT,1,1) = 0 THEN RETURN IN_STR; END IF ; LEN_DLMT:= LENGTH(DLMT); RESULT := DLMT; FOR TMP_CUR_STR IN CUR_STR LOOP IF INSTR(RESULT, DLMT || TMP_CUR_STR.STR ||DLMT, 1) = 0 THEN --没出现过的子字符串,拼接到输出字符串,再拼接一个分隔符 RESULT := RESULT || TMP_CUR_STR.STR ||DLMT; END IF; END LOOP; --去掉首尾的分隔符 RESULT:=SUBSTR(RESULT,LEN_DLMT+1,LENGTH(RESULT)-2*LEN_DLMT); RETURN RESULT; END;
这个函数的特点就是可以保持原来字符串的顺序不变,因为用group by的话字符串的顺序就改变了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。