2014-11-01 4 views
0

'n'행을 열 그룹으로 분할해야하는 상황이 있습니다. 예를 들어, 다음은 데이터 세트'n'행을 열로 그룹화 - oracle

입니다
COMMENT_TEXT 
    T1 
    T2 
    T3 
    T4 
    T5 
    T6 

예상 출력 :

SUN MON TUE 
    T1 T2 T3 
    T4 T5 T6 

내 쿼리 :

SELECT htbp1.comment_text 
FROM hxc_time_building_blocks htbp, 
    hxc_time_building_blocks htbp1 
    WHERE  htbp1.parent_building_block_id = htbp.time_building_block_id 
    AND htbp1.parent_building_block_ovn = htbp.parent_building_block_ovn 
    AND htbp.parent_building_block_id = 116166 
    AND htbp.parent_building_block_ovn = 1  
ORDER BY htbp1.time_building_block_id 

가 나는 'N'행이 골재없이 PIVOT을 할 수있는 방법이 있나요 기능?

편집 : 샘플 데이터 세트는 T1/T2/T3이지만 실제로는 임의의 자유 텍스트 또는 null 일 수 있습니다.

SELECT * FROM (SELECT htbp1.comment_text, TO_CHAR (htbp.start_time, 'DY') par_time, 
trunc((rownum-1)/7) buck 
FROM hxc_time_building_blocks htbp, 
hxc_time_building_blocks htbp1, 
hxc_timecard_summary hts 
WHERE  hts.RESOURCE_ID = :p_resource_id 
       AND TRUNC(hts.STOP_TIME) = TRUNC(:p_wkend_date) 
    AND htbp1.parent_building_block_id = htbp.time_building_block_id 
AND htbp1.parent_building_block_ovn = htbp.parent_building_block_ovn 
AND htbp.parent_building_block_id = hts.timecard_id 
AND htbp.parent_building_block_ovn = hts.timecard_ovn  
ORDER BY htbp1.time_building_block_id) PIVOT(max(comment_text) FOR par_time 
                IN ('SUN' AS "SUN", 
                 'MON' AS "MON", 
                 'TUE' AS "TUE", 
                 'WED' AS "WED", 
                 'THU' AS "THU", 
                 'FRI' AS "FRI", 
                 'SAT' AS "SAT")); 

나는 다음 데이터가 미친 거 부모 인 다른 테이블 'hxc_timecard_summary'을 추가 할 때,하지만 난 처음에 하나 같이 하드 코드 된 매개 변수를 사용하는 경우 다음 행은 미세을 보이고있다.

답변

2

PIVOT는 집계 함수를 사용하지만 당신이에 GROUP BY 필요가 없습니다 또한

with tab as (
    select sysdate - 7 date_col, 'T1' comment_text from dual 
    union all select sysdate - 6, 'T2' from dual 
    union all select sysdate - 5, 'T3' from dual 
    union all select sysdate - 4, 'T4' from dual 
    union all select sysdate - 3, 'T5' from dual 
    union all select sysdate - 2, 'T6' from dual 
    union all select sysdate - 1, 'T7' from dual 
) 
select * from (select to_char(date_col, 'D') day_of_week, comment_text from tab) 
PIVOT (max(comment_text) for day_of_week in (7 as sun, 1 as mon, 2 as tue)); 

, 난 당신이 새 열을 형성하는 날짜가 두 번째 열을 필요로 가정합니다.

FOR 절에 식을 사용할 수 없습니다.이 열은이어야합니다. 예를 들어,이 작동하지 않습니다 : to_char(date_col, 'D')

+0

당신은 최고입니다. 정말 고맙습니다. 두 번째 PIVOT은 작동했지만 한 가지 더 문제가 있습니다. 수정 된 질문을보실 수 있습니까? – Phani

+0

@Phani, trunc ((rownum-1)/7) buck - 너는 이것이 필요 없어. – Multisync

+0

@Phani DY - NLS에 따라 다르므로 조심해. – Multisync

0

pivot을 사용해보세요. 행을 열에 매핑 할 수 있습니다. 11g 이후부터 믿습니다.

+0

여기서 문제는 테이블 구조가 트리 기반이고 주석이 트리의 2 노드 아래에 있다는 점입니다. 그래서 Pivot은 예를 들어 여러 행을 던지고 있습니다. 7 일이 있고 부모 노드에 두 개의 자식이 있으면 14 개의 행이 반환됩니다. – Phani

0
with tab as (
    select 'T1' comment_text from dual 
    union all select 'T2' from dual 
    union all select 'T3' from dual 
    union all select 'T4' from dual 
    union all select 'T5' from dual 
    union all select 'T6' from dual 
) 
select regexp_substr(txt, '[^,]+', 1, 1) sun, 
     regexp_substr(txt, '[^,]+', 1, 2) mon, 
     regexp_substr(txt, '[^,]+', 1, 3) tue 
from (
    select buck, wm_concat(comment_text) txt 
    from (
    select comment_text, trunc((rownum-1)/3) buck 
    from (select comment_text from tab order by comment_text) 
)  
    group by buck 
); 

wm_concat(comment_text) (오라클 10g) =
listagg(comment_text, ',') within group(order by comment_text) (오라클 11g)의

그러나이 두 가지 기능을 모두 집계됩니다

select * from tab 
PIVOT (max(comment_text) for to_char(date_col, 'D') in (7 as sun, 1 as mon, 2 as tue)); 

때문에

0

제 3 번 시도해보십시오. 집계 함수가 전혀 없습니다 (Oracle 10g에서 올바르게 작동 함).

with tab as (
    select 'T1' comment_text from dual 
    union all select 'T2' from dual 
    union all select 'T3' from dual 
    union all select 'T4' from dual 
    union all select 'T5' from dual 
    union all select 'T6' from dual 
) 

select regexp_substr(txt, '[^(#####)]+', 1, 1) sun, 
     regexp_substr(txt, '[^(#####)]+', 1, 2) mon, 
     regexp_substr(txt, '[^(#####)]+', 1, 3) tue 
from (
    select sys_connect_by_path(comment_text, '#####') txt, parent_id 
    from (
    select rownum id, comment_text, mod(rownum-1, 3) parent_id 
    from (select comment_text from tab order by comment_text) 
) 
    start with parent_id = 0 
    connect by prior id = parent_id  
) where parent_id = 2; 
+0

나는 내 질문을 업데이 트 했으므로 패턴이없는 임의의 텍스트가 있으면 작동합니까? – Phani

+0

@Phani sys_connect_by_path (comment_text, ',') - 텍스트에 표시 할 수없는 기호를 사용해야합니다 (regexp_substr과 동일) – Multisync

+0

@Phani 또는 기호 시퀀스 (내 대답이 업데이트되었습니다) – Multisync