sql >> データベース >  >> RDS >> Oracle

Oracleでregexp_replaceによってコンマ区切りのリストから重複を削除するにはどうすればよいですか?

    SQLのみを使用する2つのソリューションと、非常に短い最終SQLクエリを作成する小さい/単純なPL/SQL関数を使用する3番目のソリューション。

    Oracleセットアップ

    CREATE TABLE data ( value ) AS
    SELECT 'POW,POW,POWPRO,PRO,PRO,PROUTL,TNEUTL,TNEUTL,UTL,UTLTNE,UTL,UTLTNE' FROM DUAL;
    
    CREATE TYPE stringlist AS TABLE OF VARCHAR2(4000);
    /
    

    クエリ1

    SELECT LISTAGG( t.COLUMN_VALUE, ',' ) WITHIN GROUP ( ORDER BY t.COLUMN_VALUE ) AS list
    FROM   data d,
           TABLE(
             SET(
               CAST(
                 MULTISET(
                  SELECT REGEXP_SUBSTR( d.value, '[^,]+', 1, LEVEL )
                  FROM   DUAL
                  CONNECT BY LEVEL <= REGEXP_COUNT( d.value, '[^,]+' )
                 ) AS stringlist
               )
             )
           ) t
    GROUP BY d.value;
    

    出力

    LIST
    ---------------------------------------
    POW,POWPRO,PRO,PROUTL,TNEUTL,UTL,UTLTNE
    

    クエリ2

    SELECT ( SELECT LISTAGG(  COLUMN_VALUE, ',' ) WITHIN GROUP ( ORDER BY ROWNUM )
             FROM TABLE( d.uniques ) ) AS list
    FROM   (
      SELECT ( SELECT CAST(
                        COLLECT(
                          DISTINCT
                          REGEXP_SUBSTR( d.value, '[^,]+', 1, LEVEL )
                        )
                        AS stringlist
                      )
                FROM  DUAL
                CONNECT BY LEVEL <= REGEXP_COUNT( d.value, '[^,]+' )
             ) uniques
      FROM   data d
    ) d;
    

    出力

    LIST
    ---------------------------------------
    POW,POWPRO,PRO,PROUTL,TNEUTL,UTL,UTLTNE
    

    Oracleセットアップ

    小さなヘルパー関数:

    CREATE FUNCTION split_String(
      i_str    IN  VARCHAR2,
      i_delim  IN  VARCHAR2 DEFAULT ','
    ) RETURN stringlist DETERMINISTIC
    AS
      p_result       stringlist := stringlist();
      p_start        NUMBER(5) := 1;
      p_end          NUMBER(5);
      c_len CONSTANT NUMBER(5) := LENGTH( i_str );
      c_ld  CONSTANT NUMBER(5) := LENGTH( i_delim );
    BEGIN
      IF c_len > 0 THEN
        p_end := INSTR( i_str, i_delim, p_start );
        WHILE p_end > 0 LOOP
          p_result.EXTEND;
          p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
          p_start := p_end + c_ld;
          p_end := INSTR( i_str, i_delim, p_start );
        END LOOP;
        IF p_start <= c_len + 1 THEN
          p_result.EXTEND;
          p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
        END IF;
      END IF;
      RETURN p_result;
    END;
    /
    

    クエリ3

    SELECT ( SELECT LISTAGG(  COLUMN_VALUE, ',' ) WITHIN GROUP ( ORDER BY ROWNUM )
             FROM TABLE( SET( split_String( d.value ) ) ) ) AS list
    FROM   data d;
    

    または(単一の値のみを渡したい場合):

    SELECT LISTAGG(  COLUMN_VALUE, ',' ) WITHIN GROUP ( ORDER BY ROWNUM ) AS list
    FROM   TABLE( SET( split_String(
              'POW,POW,POWPRO,PRO,PRO,PROUTL,TNEUTL,TNEUTL,UTL,UTLTNE,UTL,UTLTNE'
           ) ) );
    

    出力

    LIST
    ---------------------------------------
    POW,POWPRO,PRO,PROUTL,TNEUTL,UTL,UTLTNE
    


    1. PL/pgSQL関数のSELECTまたはPERFORM

    2. Oracle:2つの日付から平日を除外するまでの日数の負の数の処理方法

    3. MyBatisインサートリストの値

    4. Oracleすべてのテーブルのすべての列で文字列を検索