2016-10-10 45 views
3

我有一個Oracle表,它用作項目編號標識符的活動日誌/變更跟蹤器。我想採取最後三個變化,並以列格式列出。Oracle將行數據作爲指定數量的唯一條目的列返回

的樣本數據

Item_No Shipping_date  Last_updated 
100  01-Sep-16   24-Aug-16 
101  10-Sep-16   24-Aug-16 
102  31-Aug-16   24-Aug-16 
101  11-Sep-16   25-Aug-16 
101  12-Sep-16   26-Aug-16 
100  31-Aug-16   27-Aug-16 
102  01-Sep-16   27-Aug-16 
103  01-Oct-16   27-Aug-16 

Expected output would be: 
Item_No Shipping_1 Updated_1 Shipping_2 Updated_2 Shipping_3 Updated_3 
100  01-Sep-16 24-Aug-16 31-Aug-16 27-Aug-16 
101  10-Sep-16 24-Aug-16 11-Sep-16 25-Aug-16 12-Sep-16 26-Aug-16 
102  31-Aug-16 24-Aug-16 01-Sep-16 27-Aug-16 
103  01-Oct-16 27-Aug-16 

人有什麼想法?我已經搞亂了PIVOT,DECODE,但我似乎無法得到任何工作。我來最接近的是這樣的:

SELECT 
    ITEM_NO, 
    LISTAGG(TO_CHAR(Shipping_date, 'DD-MON-YY') || ' ' || TO_CHAR(Last_updated, 'DD-MON-YY')) 
    WITHIN GROUP 
    (ORDER BY Last_updated) Shipping_date 
FROM SHIPPING_DETAIL 
GROUP BY Item_No 
HAVING COUNT(*) > 1 

回答

1

甲骨文PIVOT可以工作:

with test_data (item_no, shipping_date, last_updated) as (
SELECT 100, to_date(  '01-Sep-16','DD-MON-YY'), to_date('24-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 101, to_date(  '10-Sep-16','DD-MON-YY'), to_date('24-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 102, to_date(  '31-Aug-16','DD-MON-YY'), to_date('24-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 101, to_date(  '11-Sep-16','DD-MON-YY'), to_date('25-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 101, to_date(  '12-Sep-16','DD-MON-YY'), to_date('26-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 100, to_date(  '31-Aug-16','DD-MON-YY'), to_date('27-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 102, to_date(  '01-Sep-16','DD-MON-YY'), to_date('27-Aug-16','DD-MON-YY') FROM DUAL UNION ALL 
SELECT 103, to_date(  '01-Oct-16','DD-MON-YY'), to_date('27-Aug-16','DD-MON-YY') FROM DUAL 
)SELECT item_no, 
     event_1_shipping, 
     event_1_last_updated, 
     event_2_shipping, 
     event_2_last_updated, 
     event_3_shipping, 
     event_3_last_updated 
FROM (SELECT last_3.item_no, 
       last_3.shipping_date, 
       last_3.last_updated, 
       ROW_NUMBER() OVER (PARTITION BY item_no ORDER BY filter_rown DESC) rown 
     FROM (SELECT td.*, 
         ROW_NUMBER() OVER (PARTITION BY item_no ORDER BY last_updated DESC) filter_rown 
       FROM test_data td) last_3 
     WHERE filter_rown <= 3) PIVOT (MIN (shipping_date) "SHIPPING", MIN (last_updated) "LAST_UPDATED" 
           FOR rown 
           IN (1 AS "EVENT_1", 2 AS "EVENT_2", 3 AS "EVENT_3")) 

***從我原來的答案編輯,以使事件從最早的被分揀到最新。

+0

幹得漂亮。爲了確切得到OP所要求的內容,我相信查詢需要使用'order by shipping_date asc'命令 - 雖然即使這樣也不適用於ITEM_NO 100. –

+0

看起來像'LAST_UPDATED ASC'。對不起,我不小心 - 謝謝你指出。我會更新。 –

+0

只需完成評論鏈:我需要在答案中添加另一個'ROW_NUMBER()',以分隔用於過濾最後3個事件的過濾器和用於排序列的過濾器。 –

0

一個小竅門,你可以做兩個步驟:rnrow_number() over last_updated desc,但調整時的item_no計數爲小(1或2),這樣,當我們轉動,日期在排隊適當的專欄。然後像往常一樣PIVOT

with test_data (item_no, shipping_date, last_updated) as (
     select 100, to_date('01-Sep-16','dd-mon-yy'), to_date('24-Aug-16','dd-mon-yy') from dual union all 
     select 101, to_date('10-Sep-16','dd-mon-yy'), to_date('24-Aug-16','dd-mon-yy') from dual union all 
     select 102, to_date('31-Aug-16','dd-mon-yy'), to_date('24-Aug-16','dd-mon-yy') from dual union all 
     select 101, to_date('11-Sep-16','dd-mon-yy'), to_date('25-Aug-16','dd-mon-yy') from dual union all 
     select 101, to_date('12-Sep-16','dd-mon-yy'), to_date('26-Aug-16','dd-mon-yy') from dual union all 
     select 100, to_date('31-Aug-16','dd-mon-yy'), to_date('27-Aug-16','dd-mon-yy') from dual union all 
     select 102, to_date('01-Sep-16','dd-mon-yy'), to_date('27-Aug-16','dd-mon-yy') from dual union all 
     select 103, to_date('01-Oct-16','dd-mon-yy'), to_date('27-Aug-16','dd-mon-yy') from dual 
    ), 
    prep (item_no, shipping_date, last_updated, rn) as (
     select item_no, shipping_date, last_updated, 
       row_number() over (partition by item_no order by last_updated desc) 
        + greatest(0, 3 - count(*) over (partition by item_no)) 
     from test_data 
    ) 
select item_no, "3_SHIPPING" as shipping_1, "3_UPDATED" as updated_1, 
       "2_SHIPPING" as shipping_2, "2_UPDATED" as updated_2, 
       "1_SHIPPING" as shipping_3, "1_UPDATED" as updated_3 
from prep 
pivot (
     min(shipping_date) as shipping, min(last_updated) as updated for rn in (1, 2, 3) 
    ) 
order by item_no; 

OUTPUT: 

    ITEM_NO SHIPPING_1 UPDATED_1 SHIPPING_2 UPDATED_2 SHIPPING_3 UPDATED_3 
---------- ----------- ----------- ----------- ----------- ----------- ----------- 
     100 01-SEP-2016 24-AUG-2016 31-AUG-2016 27-AUG-2016       
     101 10-SEP-2016 24-AUG-2016 11-SEP-2016 25-AUG-2016 12-SEP-2016 26-AUG-2016 
     102 31-AUG-2016 24-AUG-2016 01-SEP-2016 27-AUG-2016       
     103 01-OCT-2016 27-AUG-2016             
0

我做出了榜樣,而不轉動

with s as (
select 100 o, date'2016-09-01' as sh,date'2016-08-24' as up from dual union all 
select 101 o, date'2016-09-10' as sh,date'2016-08-24' as up from dual union all 
select 102 o, date'2016-08-31' as sh,date'2016-08-24' as up from dual union all 
select 101 o, date'2016-09-11' as sh,date'2016-08-25' as up from dual union all 
select 101 o, date'2016-09-12' as sh,date'2016-08-26' as up from dual union all 
select 100 o, date'2016-08-31' as sh,date'2016-08-27' as up from dual union all 
select 102 o, date'2016-09-01' as sh,date'2016-08-27' as up from dual union all 
select 103 o, date'2016-10-01' as sh,date'2016-08-27' as up from dual 
) 
, ordering as(
select o, 
     sh, 
     count(*) over (partition by o) - 
     row_number() over (partition by o order by up desc) r 
     ,up from s) 
    select o as item_no 
     , max(decode(r,0,sh)) as shipping_1, max(decode(r,0,up)) as updated_1  
     , max(decode(r,1,sh)) as shipping_2, max(decode(r,1,up)) as updated_2  
     , max(decode(r,2,sh)) as shipping_3, max(decode(r,2,up)) as updated_3 
    from ordering 
    group by o; 
相關問題