2013-11-22 2 views
2

원래 테이블 (정확히 하나 나는 모든 쉼표 브래킷 등으로 .. 사용하고 그)문자열을 Teradata에서 그룹화 할 수 있습니까?

id  attributes 
1  123(red), 139(red), 123(white), 123(black), 139(white), 
2  123(black), 139(white), 123(green), 
32  223(blue), 223(red), 553(white), 123(black), 
4  323(white), 139(red), 
23  523(red), 

내 테이블

id  attributes 
1  123(red, white, black); 139(red, white); 
2  123(black, green); 139(white); 
32  223(blue, red); 553(white); 123(black); 
4  323(white); 139(red); 
23  523(red); 

어떻게처럼 보이도록 내가 그룹에 속성 번호가 필요합니다 나는 이것을한다?

불행히도 나는 oreplace .. translate 같은 저장 프로 시저 및 함수에 액세스 할 수 없습니다. 내가 이전에 오라클을 다루는 데 사용되는 하나는 저장 프로 시저에 대한 액세스 권한이 주어진 쉬운 작업입니다 ... 여기에 내가 뭘 해야할지 전혀 모르겠다

+2

실제로 속성을 쉼표로 구분 된 목록으로 표시합니까? 그리고 그것을 완전히 다른 비정규 화 된 형식으로 변환하고 싶습니까? 물론 속성을 표준화 열과 다시 집계로 나눌 수 있지만 액세스 방법에 따라 클라이언트 쪽에서 더 쉽게 수행 할 수 있습니다. – dnoeth

+0

고맙습니다. 위의 테이블은 실제 테이블입니다. 위의 표는 모든 쉼표와 세미콜론으로 excatly 동일합니다. 변형은 어떻게 할 수 있습니까? @dnoeth –

+0

어떤 버전의 Teradata를 사용하십니까? –

답변

10

SQL은 분명히 그런 문자열 처리를 수행하는 올바른 언어가 아닙니다 :)

기존 코드를 사용하여 쉼표로 분리 된 문자열을 분할/작성했지만 TD14에서는 훨씬 쉬울 것입니다 (strtok_split_to_table 및 udfConcat이 있습니다).

CREATE VOLATILE TABLE vt (id INT, attrib VARCHAR(100)) ON COMMIT PRESERVE ROWS; 

INSERT INTO vt(1  ,'123(red), 139(red), 123(white), 123(black), 139(white),'); 
INSERT INTO vt(2  ,'123(black), 139(white), 123(green),'); 
INSERT INTO vt(32  ,'223(blue), 223(red), 553(white), 123(black),'); 
INSERT INTO vt(4  ,'323(white), 139(red), '); 
INSERT INTO vt(23  ,'523(red),'); 

WITH RECURSIVE cte 
(id, 
    len, 
    remaining, 
    word, 
    pos 
) AS (
    SELECT 
    id, 
    POSITION(',' IN attrib || ',') - 1 AS len, 
    SUBSTRING(attrib || ',' FROM len + 2) AS remaining, 
    TRIM(SUBSTRING(attrib FROM 1 FOR len)) AS word, 
    1 
    FROM vt 
    UNION ALL 
    SELECT 
    id, 
    POSITION(',' IN remaining)- 1 AS len_new, 
    SUBSTRING(remaining FROM len_new + 2), 
    TRIM(SUBSTRING(remaining FROM 1 FOR len_new)), 
    pos + 1 
    FROM cte 
    WHERE remaining <> '' 
) 
SELECT 
    id, 
    MAX(CASE WHEN newpos = 1 THEN newgrp ELSE '' END) || 
    MAX(CASE WHEN newpos = 2 THEN newgrp ELSE '' END) || 
    MAX(CASE WHEN newpos = 3 THEN newgrp ELSE '' END) || 
    MAX(CASE WHEN newpos = 4 THEN newgrp ELSE '' END) || 
    MAX(CASE WHEN newpos = 5 THEN newgrp ELSE '' END) || 
    MAX(CASE WHEN newpos = 6 THEN newgrp ELSE '' END) 
    -- add as many CASEs as needed 
FROM 
( 
    SELECT 
    id, 
    ROW_NUMBER() 
    OVER (PARTITION BY id 
      ORDER BY newgrp) AS newpos, 
    a || 
    MAX(CASE WHEN pos = 1 THEN '(' || b ELSE '' END) || 
    MAX(CASE WHEN pos = 2 THEN ', ' || b ELSE '' END) || 
    MAX(CASE WHEN pos = 3 THEN ', ' || b ELSE '' END) || 
    MAX(CASE WHEN pos = 4 THEN ', ' || b ELSE '' END) || 
    MAX(CASE WHEN pos = 5 THEN ', ' || b ELSE '' END) || 
    MAX(CASE WHEN pos = 6 THEN ', ' || b ELSE '' END) 
    -- add as many CASEs as needed 
    || '); ' AS newgrp 
    FROM 
    (
     SELECT 
     id, 
     ROW_NUMBER() 
     OVER (PARTITION BY id, a 
       ORDER BY pos) AS pos, 
     SUBSTRING(word FROM 1 FOR POSITION('(' IN word) - 1) AS a, 
     TRIM(TRAILING ')' FROM SUBSTRING(word FROM POSITION('(' IN word) + 1)) AS b 
     FROM cte 
     WHERE word <> '' 
    ) AS dt 
    GROUP BY id, a 
) AS dt 
GROUP BY id; 
+0

당신은 최고입니다. 덕분에 –

+0

마술처럼 일했습니다. –

관련 문제