복붙노트

[SQL] 분할 쉼표는 오라클의 열 값을 분리

SQL

분할 쉼표는 오라클의 열 값을 분리

I 값 255 콤마 구분 값으로 반환있다. 255 SUBSTR없이 열로 사람들을 분할하는 쉬운 방법이 있나요?

ROW  | VAL
----------- 
1    | 1.25, 3.87, 2, ... 
2    | 5, 4, 3.3, ....

ROW | VAL | VAL | VAL ...
--------------------- 
1   |1.25 |3.87 | 2 ...     
2   | 5   | 4   | 3.3 ...

해결법

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

    1.당신은) (REGEXP_SUBSTR을 사용할 수 있습니다 :

    당신은) (REGEXP_SUBSTR을 사용할 수 있습니다 :

    select regexp_substr(val, '[^,]+', 1, 1) as val1, 
           regexp_substr(val, '[^,]+', 1, 2) as val2, 
           regexp_substr(val, '[^,]+', 1, 3) as val3, 
           . . .
    

    나는 Excel에서 255 개 번호의 열 (또는 다른 스프레드 시트)를 생성 할 것을 제안하고, SQL 코드를 생성하기 위해 스프레드 시트를 사용합니다.

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

    2.주의! 이 목록에서 널 요소이며 해당 항목이나 뒤에 하나를 원하는 경우 형식의 REGEXP_SUBSTR 식 '[^,] +'예상 값을 반환하지 않습니다. '5'를 반환 할 것으로 예상 따라서 4 요소가 NULL이 예제를 고려하고 나는 5 요소를 원하는 :

    주의! 이 목록에서 널 요소이며 해당 항목이나 뒤에 하나를 원하는 경우 형식의 REGEXP_SUBSTR 식 '[^,] +'예상 값을 반환하지 않습니다. '5'를 반환 할 것으로 예상 따라서 4 요소가 NULL이 예제를 고려하고 나는 5 요소를 원하는 :

    SQL> select regexp_substr('1,2,3,,5,6', '[^,]+', 1, 5) from dual;
    
    R
    -
    6
    

    놀라다! 그것은 5의 비 NULL 요소가 아닌 실제 5 번째 요소를 반환! 잘못된 데이터가 반환하고 당신도 그것을 잡을 수 없습니다. 대신이 시도 :

    SQL> select regexp_substr('1,2,3,,5,6', '(.*?)(,|$)', 1, 5, NULL, 1) from dual;
    
    R
    -
    5
    

    그래서, 보정 REGEXP_SUBSTR 위는 (다음 분리 가능 그것을 콤마 또는 라인의 단부 일) 0 콤마 구분 문자 5 발생 쉼표 또는 라인의 끝 뒤에보고 말한다 반환을 (데이터 라인의 쉼표 또는 끝 제외) 1 서브 그룹을 발견했을 때.

    검색 일치하는 패턴 '(.? *) (| $)'설명 :

    (             = Start a group
    .             = match any character
    *             = 0 or more matches of the preceding character
    ?             = Match 0 or 1 occurrences of the preceding pattern
    )             = End the 1st group
    (             = Start a new group (also used for logical OR)
    ,             = comma
    |             = OR
    $             = End of the line
    )             = End the 2nd group
    

    편집 : 더 많은 정보를 추가하고, 정규식을 단순화.

    추가 정보를 쉽게 재사용하는 기능이 캡슐화하는 제안이 게시물을 참조 : 정규식 널 (null)을 허용 목록에서 n 번째 값을 선택합니다 내가 형식 '[^,] +'는 문제가 발견 포스트입니다. 불행하게도 당신이 가장 일반적으로 목록을 구문 분석하는 방법에 관한 질문에 대한 답변으로 볼 수 정규식 형식입니다. 나는 '[^,] +'모든 잘못된 데이터에 의해 반환되는 생각 떤다!

  3. ==============================

    3.만 만들 수있는 하나의 행, 시간이 있으면

    만 만들 수있는 하나의 행, 시간이 있으면

    select * from (
      select rownum r , collection.*  
        from TABLE(cto_table(',','1.25, 3.87, 2, 19,, 1, 9, ')) collection
    )
    PIVOT ( 
      LISTAGG(column_value) within group (order by 1) as val 
      for r in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    )
    

    참고 : 여기에 cto_table 함수를 작성하는 방법입니다 :

    CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);
    CREATE OR REPLACE
    FUNCTION cto_table(p_sep in Varchar2, p_list IN VARCHAR2)
      RETURN t_my_list
    AS
      l_string VARCHAR2(32767) := p_list || p_sep;
      l_sep_index PLS_INTEGER;
      l_index PLS_INTEGER := 1;
      l_tab t_my_list     := t_my_list();
    BEGIN
      LOOP
        l_sep_index := INSTR(l_string, p_sep, l_index);
        EXIT
      WHEN l_sep_index = 0;
        l_tab.EXTEND;
        l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_sep_index - l_index));
        l_index            := l_sep_index + 1;
      END LOOP;
      RETURN l_tab;
    END cto_table;
    /
    
  4. ==============================

    4.계층 적 쿼리를 사용할 수 있습니다. 회전을하여 케이스와 그룹 수행 할 수 있습니다.

    계층 적 쿼리를 사용할 수 있습니다. 회전을하여 케이스와 그룹 수행 할 수 있습니다.

    with value_t as
    ( 
      select row_t,row_number() OVER (partition by row_t order by rownum )rn,
      regexp_substr(val, '[^,]+', 1, LEVEL) val from Table1
    CONNECT BY LEVEL <= regexp_count(val, '[^,]+') 
    AND prior row_t = row_t 
    AND prior sys_guid() is not null
      ) select row_t, max( case when rn = 1 THEN val end ) val_1,
      max( case when rn = 2 THEN val end ) val_2,
      max( case when rn = 3 THEN val end ) val_3
      from value_t
      group by row_t;
    
  5. from https://stackoverflow.com/questions/31464275/split-comma-separated-values-to-columns-in-oracle by cc-by-sa and MIT license