从 Oracle 中的逗号分隔变量中删除重复值

AVr*_*let 3 regex sql oracle plsql oracle-apex

我有一个变量(称为:all_email_list),其中总共包含 3 个电子邮件地址列表。(我发现了一些类似的问题,但与正确的解决方案不同)

示例:(test@asd.com, test2@asd.com,test@asd.com,test3@asd.com, test4@asd.com,test2@asd.com逗号之间可以包含空格,但并非始终如此)

所需的输出:test@asd.com, test2@asd.com,test3@asd.com,test4@asd.com

declare
first_email_list varchar2(4000);
second_email_list varchar2(4000);
third_email_list varchar2(4000);
all_email_list varchar2(4000);

begin

    select listagg(EMAIL,',') into first_email_list from UM_USER a left join UM_USERROLLE b on (a.mynetuser=b.NT_NAME) left join UM_RULES c on (c.id=b.RULEID) where RULEID = 902;
    select listagg(EMAIL,',') into second_email_list from table2 where CFT_ID =:P25_CFT_TEAM; 
    select EMAIL into third_email_list from table3 WHERE :P25_ID = ID;


    all_email_list:= first_email_list || ',' || second_email_list || ',' || third_email_list; 

    dbms_output.put_line(all_email_list);
end;
Run Code Online (Sandbox Code Playgroud)

有什么办法可以简单地解决这个问题吗?也许通过正则表达式。

Koe*_*rie 6

解决方案描述。首先使用 CTE 将电子邮件列表拆分为行,每行 1 个电子邮件地址 (testd_rows)。然后从 testd_rows 中选择不同的行(testd_rows_unique),最后用 listagg 将它们放回一起。从 19c 开始,您可以使用LISTAGGwithDISTINCT关键字。

set serveroutput on size 999999
clear screen
declare

  all_email_list varchar2(4000);
  l_unique_email_list varchar2(4000);
  

begin
  all_email_list := 'test@asd.com, test2@asd.com,test@asd.com,test3@asd.com, test4@asd.com,test2@asd.com';

  WITH testd_rows(email) AS
  (
  select regexp_substr (all_email_list, '[^, ]+', 1, rownum) split  
    from dual 
  connect by level <= length (regexp_replace (all_email_list, '[^, ]+'))  + 1
  ), testd_rows_unique(email) AS
  (
  SELECT distinct email FROM testd_rows
  )
  SELECT listagg(email, ',') WITHIN GROUP (ORDER BY email) 
    INTO l_unique_email_list 
    FROM testd_rows_unique;

  dbms_output.put_line(l_unique_email_list);
end;
/

test2@asd.com,test3@asd.com,test4@asd.com,test@asd.com
Run Code Online (Sandbox Code Playgroud)

但是...为什么要将行转换为逗号分隔的字符串,然后对其进行重复数据删除?用于UNION取出单个SELECT语句中的重复值并对LISTAGG这些值执行操作。那时不需要正则表达式。UNION将跳过重复项,而不是UNION ALL返回所有行。

DECLARE
  all_email_list varchar2(4000);
BEGIN
  WITH all_email (email) AS
  (
    select email from UM_USER a left join UM_USERROLLE b on (a.mynetuser=b.NT_NAME) left join UM_RULES c on (c.id=b.RULEID) where RULEID = 902
    UNION
    select email from table2 where CFT_ID =:P25_CFT_TEAM
    UNION
    select email from table3 WHERE :P25_ID = ID
  )
  SELECT listagg(email, ',') WITHIN GROUP (ORDER BY email) 
    INTO all_email_list 
    FROM all_email;

  dbms_output.put_line(all_email_list);
END;
/
Run Code Online (Sandbox Code Playgroud)