【问题标题】:oracle function for: select distinct values count from comma separated stringoracle函数:从逗号分隔的字符串中选择不同的值计数
【发布时间】:2021-06-07 07:36:50
【问题描述】:

我需要一个 Oracle (11) 函数来处理这个问题。 我需要从逗号分隔的字符串中计算不同的值。

例如逗号分隔的字符串: 'Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text'

结果必须是 = 6

因为

  1. 洛雷姆
  2. Ipsum
  3. 简单
  4. 假人
  5. 文字

我想这样使用

select fn_dist_count_values_in_list_arr('Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text') from dual;

谁能帮忙写这个(“fn_dist_count_values_in_list_arr”)oracle函数?

【问题讨论】:

    标签: oracle function distinct distinct-values csv


    【解决方案1】:

    另一种方法是使用分层查询将逗号分隔的值拆分为一组行(with 子句)并针对它运行一个简单的 sql 查询

    with str_parsed as (SELECT REGEXP_SUBSTR('Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text', '[^,]+', 1, LEVEL) val
                        FROM dual
                        CONNECT BY REGEXP_SUBSTR('Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text', '[^,]+', 1, LEVEL) IS NOT NULL)
    select count(distinct val) from str_parsed
    

    【讨论】:

      【解决方案2】:

      您不需要从 SQL 到 PL/SQL 函数的上下文切换,并且可以在 SQL 中完成所有操作:

      SELECT ( SELECT COUNT( DISTINCT CAST(column_value AS VARCHAR2(20)) )
               FROM   XMLTABLE( ('"'||REPLACE(value,',','","')||'"') ) )
               AS num_distinct_values
      FROM   table_name
      

      其中,对于样本数据:

      CREATE TABLE table_name ( value ) AS
      SELECT 'Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text,Lorem,Ipsum,is,simply,dummy,text' FROM DUAL;
      

      输出:

      | NUM_DISTINCT_VALUES | | ------------------: | | 6 |

      如果你想要一个纯 PL/SQL 函数(这样你就没有多个上下文切换),那么:

      CREATE FUNCTION fn_dist_count_values_in_list_arr (
        list_value IN VARCHAR2
      ) RETURN NUMBER DETERMINISTIC
      IS
        TYPE t_words IS TABLE OF NUMBER(1,0) INDEX BY VARCHAR2(200);
        v_words t_words;
        v_start PLS_INTEGER := 1;
        v_end   PLS_INTEGER;
      BEGIN
        IF list_value IS NULL THEN
          RETURN 0;
        END IF;
        LOOP
          v_end := INSTR( list_value, ',', v_start );
          EXIT WHEN v_end = 0;
          v_words(SUBSTR(list_value, v_start, v_end - v_start ) ) := 1;
          v_start := v_end + 1;
        END LOOP;
        v_words(SUBSTR(list_value,v_start)) := 1;
        RETURN v_words.COUNT;
      END;
      /
      

      然后:

      SELECT fn_dist_count_values_in_list_arr( value )
      FROM   table_name
      

      输出:

      | FN_DIST_COUNT_VALUES_IN_LIST_ARR(VALUE) | | --------------------------------------------------: | | 6 |

      db小提琴here

      【讨论】:

        【解决方案3】:
            CREATE OR REPLACE FUNCTION DIST_COUNT_VALUES_IN_STR_ARR
            (STR_ARR IN VARCHAR2)
            RETURN NUMBER
            AS
            DIST_COUNT NUMBER(38);
            BEGIN
                SELECT COUNT(DISTINCT COL1) 
                INTO DIST_COUNT FROM (
                    SELECT REGEXP_SUBSTR(STR_ARR,'[^,]+', 1, LEVEL) COL1 
                    FROM DUAL
                    CONNECT BY LEVEL <= REGEXP_COUNT(STR_ARR, ',') + 1
                );
                RETURN DIST_COUNT;
            END;
        

        这对我有用。内部查询通过在逗号字符上使用正则表达式将元素分成行。当我达到我的 Oracle 版本的对象名称的最大长度限制时,我不得不重命名您的函数。

        【讨论】:

          猜你喜欢
          • 2020-08-12
          • 1970-01-01
          • 2020-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多