2014-11-01 3 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 

Есть ли способ, что я могу сделать PIVOT с рядами 'N' и без заполнителя функционировать?

Редактировать: T1/T2/T3 в качестве образцов данных, но в реальности это может быть любой случайный свободный текст или нуль.

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

ОСИ также использует агрегатную функцию, но вам не нужно 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 - это должны быть столбцы (столбцы). Например, это не будет работать:

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

из to_char(date_col, 'D')

+0

Ты потрясающий. Огромное спасибо. Второй PIVOT работал, но есть еще одна проблема, с которой я столкнулся. Не могли бы вы посмотреть отредактированный вопрос? – Phani

+0

@Phani, trunc ((rownum-1)/7) buck - вам это не нужно – Multisync

+0

@Phani DY - это зависит от NLS, поэтому будьте осторожны – Multisync

0

Попробуйте использовать pivot. Позволяет сопоставлять строки столбцам. С 11-го года я верю.

+0

Проблема заключается в том, что структура таблицы основана на деревьях, а комментарий лежит под вторым узлом дерева. Таким образом, 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) (Oracle 10g) =
listagg(comment_text, ',') within group(order by comment_text) (Oracle 11g)

Но эти две функции как совокупный

0

Моя третья попытка, никаких агрегатных функций вообще (отлично работает в 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

Смежные вопросы