복붙노트

[SQL] 여러 행으로 분할 문자열

SQL

여러 행으로 분할 문자열

나는 예를 들면, 여러 컬럼 식별자 값을 포함하는 문자열 테이블이 알파벳.

나는이 문자열을 분할하고 쿼리에서 그 값을 사용해야합니다. 예를 들어 나는 다음 표했다 :

str
a;b;c
b;c;d
a;c;d

나는 그 결과 다음과 같은 얻을 STR 열에서 하나의 값으로 그룹에 필요

str count(*)
a   1
b   2
c   3
d   2

그것은 하나의 선택 쿼리를 사용하여 구현할 수 있습니까? 그 임시 테이블에 대해이 값과 쿼리를 추출하는 임시 테이블을 만들 수 없습니다.

해결법

  1. ==============================

    1.@PrzemyslawKruglej의 대답에 귀하의 코멘트에서

    @PrzemyslawKruglej의 대답에 귀하의 코멘트에서

    발생 된 열의 량은 다음의 방식으로 감소 될 수있다 :

    /* test table populated with sample data from your question */
    SQL> create table t1(str) as(
      2    select 'a;b;c'  from dual union all
      3    select 'b;c;d'  from dual union all
      4    select 'a;c;d'  from dual
      5  );
    Table created
    
    --  number of rows generated will solely depend on the most longest 
    --  string. 
    --  If (say) the longest string contains 3 words (wont count separator `;`)
    --  and we have 100 rows in our table, then we will end up with 300 rows 
    --  for further processing , no more.
    with occurrence(ocr) as( 
      select level 
        from ( select max(regexp_count(str, '[^;]+')) as mx_t
                 from t1 ) t
        connect by level <= mx_t 
    )
    select count(regexp_substr(t1.str, '[^;]+', 1, o.ocr)) as generated_for_3_rows
      from t1
     cross join occurrence o;
    

    결과 : 가장 긴 하나는 세 단어로 구성되어 세 개의 행, 우리는 9 개 행을 생성합니다 경우 :

    GENERATED_FOR_3_ROWS
    --------------------
                      9
    

    최종 쿼리 :

    with occurrence(ocr) as( 
      select level 
        from ( select max(regexp_count(str, '[^;]+')) as mx_t
                 from t1 ) t
        connect by level <= mx_t 
    )
    select res
         , count(res) as cnt
      from (select regexp_substr(t1.str, '[^;]+', 1, o.ocr) as res
              from t1
             cross join occurrence o)
     where res is not null
     group by res
     order by res;
    

    결과:

    RES          CNT
    ----- ----------
    a              2
    b              2
    c              3
    d              2
    

    SQL 휘티 d 혀라도

    더 regexp_count () (11g 이상) 및 REGEXP_SUBSTR () 정규 표현식 기능에 대해 알아보십시오.

    참고 : 계산하는 정규 표현식 기능이 상대적으로 비싼, 그것은 매우 많은 양의 데이터를 처리 할에 올 때, 그것은 일반 PL / SQL로 전환하는 것을 고려 가치가있을 수도 있습니다. 다음은 예이다.

  2. ==============================

    2.이 추한,하지만 작동하는 것 같다. 연결 BY 분할의 문제는 중복 행을 반환합니다. 나는 그들을 제거하기 위해 관리,하지만 당신은 그것을 테스트해야합니다 :

    이 추한,하지만 작동하는 것 같다. 연결 BY 분할의 문제는 중복 행을 반환합니다. 나는 그들을 제거하기 위해 관리,하지만 당신은 그것을 테스트해야합니다 :

    WITH
      data AS (
        SELECT 'a;b;c' AS val FROM dual
        UNION ALL SELECT 'b;c;d' AS val FROM dual
        UNION ALL SELECT 'a;c;d' AS val FROM dual
      )
    SELECT token, COUNT(1)
      FROM (
        SELECT DISTINCT token, lvl, val, p_val
          FROM (
            SELECT
                regexp_substr(val, '[^;]+', 1, level) AS token,
                level AS lvl,
                val,
                NVL(prior val, val) p_val
              FROM data
            CONNECT BY regexp_substr(val, '[^;]+', 1, level) IS NOT NULL
          )
        WHERE val = p_val
      )
    GROUP BY token;
    
    TOKEN                  COUNT(1)
    -------------------- ----------
    d                             2 
    b                             2 
    a                             2 
    c                             3 
  3. ==============================

    3.

    SELECT NAME,COUNT(NAME) FROM ( SELECT NAME  FROM ( (SELECT rownum as ID, REGEXP_SUBSTR('a;b;c', '[^;]+', 1, LEVEL )  NAME
           FROM dual  CONNECT BY REGEXP_SUBSTR('a;b;c', '[^;]+', 1, LEVEL) IS NOT NULL))
           UNION ALL  (SELECT NAME  FROM ( (SELECT rownum as ID, REGEXP_SUBSTR('b;c;d', '[^;]+', 1, LEVEL )  NAME
           FROM dual  CONNECT BY REGEXP_SUBSTR('b;c;d', '[^;]+', 1, LEVEL) IS NOT NULL)))
           UNION ALL 
             (SELECT NAME  FROM ( (SELECT rownum as ID, REGEXP_SUBSTR('a;c;d', '[^;]+', 1, LEVEL )  NAME
           FROM dual  CONNECT BY REGEXP_SUBSTR('a;c;d', '[^;]+', 1, LEVEL) IS NOT NULL)))) GROUP BY NAME
    
    NAME  COUNT(NAME)
    ----- -----------
    d               2
    a               2
    b               2
    c               3
    
  4. from https://stackoverflow.com/questions/20078812/split-string-into-several-rows by cc-by-sa and MIT license