【问题标题】:Remove duplicate values from comma separated variable in Oracle从 Oracle 中的逗号分隔变量中删除重复值
【发布时间】:2021-11-08 19:17:08
【问题描述】:

我有一个变量(称为: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;

有什么方法可以简单地解决这个问题吗?可能是正则表达式。

【问题讨论】:

    标签: sql regex oracle plsql oracle-apex


    【解决方案1】:

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

    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
    

    但是...为什么要将行转换为逗号分隔的字符串,然后对其进行重复数据删除?使用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;
    /
    

    【讨论】:

    • 感谢您的回答!但是在第二个解决方案中,为什么您需要第 10 行中的 into third_email_list ? @Koen Lostrie
    • 啊 - 这是一个错字。修复 !感谢您的关注
    • 谢谢!如果我的第 10 行是 select address from table3 WHERE :P25_ID = ID 而不是 select email.... ,它会起作用吗? @Koen Lostrie
    • 它应该只要数据类型相同。最好的方法是测试它:)
    【解决方案2】:

    您可以利用 apex_string.split 表函数来简化代码。

    12c+ 使其真正干净

    select listagg(distinct column_value,',') within group (order by null)
    from apex_String.split(replace('test@asd.com, test2@asd.com,test@asd.com,test3@asd.com, test4@asd.com,test2@asd.com'
                                  ,' ')
                          ,',')
    

    11g 需要一个包装 table() 而 listagg 不支持 distinct。

    select listagg(email,',') within group (order by null)
    from
     (select distinct column_value email
      from table(apex_String.split(replace('test@asd.com, test2@asd.com,test@asd.com,test3@asd.com, test4@asd.com,test2@asd.com',' '),','))
    );
    

    【讨论】:

      猜你喜欢
      • 2016-05-21
      • 2020-06-27
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多