如何在LISTAGG中将逗号替换为竖线、去重并去除末尾分隔符
问题原因
你使用的正则表达式'([^,]+)(,|\1)+'逻辑错误,导致ID=1的结果出现异常值2。具体问题在于:
(,|\1)+的匹配规则是匹配逗号,或者匹配与捕获组1完全相同的内容,这会错误地将后续字符串中与捕获组部分重合的内容也纳入匹配范围。例如处理A1,A1,A1,B12时,正则会错误拆分字符,把B12的12单独识别为匹配项,最终导致异常输出。
解决方案
需要调整正则逻辑,确保仅匹配以逗号分隔的重复元素,先完成去重,再替换分隔符并修剪末尾多余符号。以下是两种可行的修正方案:
方案1:分步处理(更易理解)
先对LISTAGG生成的字符串去重,再替换逗号为竖线:
SELECT ID, REPLACE( RTRIM( REGEXP_REPLACE( LISTAGG(user_name, ',') WITHIN GROUP (ORDER BY user_name), '([^,]+)(,\1)+', '\1' ), ',' ), ',', '|' ) AS USER_NAME FROM my_table GROUP BY ID;
方案2:合并正则处理(更简洁)
通过正则一次性完成去重和分隔符替换,最后修剪末尾竖线:
SELECT ID, RTRIM( REGEXP_REPLACE( LISTAGG(user_name, ',') WITHIN GROUP (ORDER BY user_name), '([^,]+)(,\1)*', '\1|' ), '|' ) AS USER_NAME FROM my_table GROUP BY ID;
说明
两种方案的核心逻辑都是:
- 用
([^,]+)(,\1)+(或(,\1)*)匹配重复的、以逗号分隔的相同用户名称,将其替换为单个值完成去重。 - 再将逗号替换为竖线(或直接在替换时用竖线作为分隔符)。
- 最后用
RTRIM去除末尾多余的分隔符。
执行修正后的查询后,ID=1的结果会正确显示为A1|B12|C32,其余ID的结果也符合预期。
内容的提问来源于stack exchange,提问作者BiSaM
相关产品推荐
相关产品推荐

