2014-10-10 90 views
1

我有2個表:ORACLE SQL基於不同的基於時間的事件連接表

  • PROCESSOR_EVENT(ID,時間,機,名稱,狀態)
  • COMM_EVENT(ID,時間,機,名稱,類型)

我想檢索PROCESSOR_EVENT.Time和下一個PROCESSOR_EVENT.Time之前的下一個COMM_EVENT之間的時間差。

即在下一個PROCESSOR_EVENT之前發生的PROCESSOR_EVENT之後的第一個COMM_EVENT事件。

示例數據:

PROCESSOR_EVENT(Id, Time, Machine, Name, State) 
1, 01:00:00, TRX4, Ignition, Heated 
2, 01:00:03, TRX1, Movement, Triangulating 
3, 01:00:23, TRX4, Movement, Heated 
4, 01:00:32, TRX4, Direction Change, Stable 
5, 01:00:56, TRX4, Stopping, Heated 

COMM_EVENT(Id, Time, Machine, Name, Type) 
1, 01:00:02, TRX4, Direction request, Request 
2, 01:00:15, TRX4, Direction acknowledgement, Acknowledgement 
3, 01:00:16, TRX1, Position change, Command 
4, 01:00:34, TRX4, Direction request, Request 
5, 01:01:02, TRX4, Position change, Command 

預期回報:

PROCESSOR_EVENT.Time, PROCESSOR_EVENT.Machine, PROCESSOR_EVENT.Name, COMM_EVENT.Time, COMM_EVENT.Type, TimeDifference 
01:00:00, TRX4, Ignition, 01:00:02, Request, 2 
01:00:03, TRX1, Movement, 01:00:16, Command, 13 
01:00:23, TRX4, Movement, null, null, null 
01:00:32, TRX4, Direction Change, 01:00:34, Request, 11 
01:00:56, TRX4, Stopping, 01:01:02, Command, 6 

如何去這樣做將是巨大的任何想法,在此先感謝您的時間。

+0

您可以嘗試延遲和主導功能。 – Nitish 2014-10-10 07:10:21

+1

在您預期的回報中是否應該將處理器事件4與通信事件4結合在一起?處理器事件3沒有相應的通信事件?你說你想在下一個處理器事件之前進行下一個comm事件。在處理器事件3之後但在下一個處理器事件(它是4)之前沒有發生通信事件。對? – 2014-10-10 07:48:29

+0

是的,你說得對,謝謝你指出,我已經更新了。 – 2014-10-10 08:04:34

回答

1

嘗試此查詢:

SELECT 
    TO_CHAR(t.Time, 'HH24:MI:SS') AS "PROCESSOR_EVENT.Time", 
    t.Machine AS "PROCESSOR_EVENT.Machine", 
    t.Name AS "PROCESSOR_EVENT.Name", 
    TO_CHAR(t.ce_time, 'HH24:MI:SS') AS "COMM_EVENT.Time", 
    t.ce_type AS "COMM_EVENT.Type", 
    (t.ce_time - t.Time)*24*60*60 AS TimeDifference 
FROM (
    SELECT pe.*, 
    ROW_NUMBER() OVER (PARTITION BY pe.ID ORDER BY ce.Time) AS rn, 
    ce.Time AS ce_time, 
    ce.Type AS ce_type 
    FROM (
    SELECT PROCESSOR_EVENT.*, 
     LEAD(Time) OVER (PARTITION BY Machine ORDER BY Time) AS next_pe_time 
    FROM PROCESSOR_EVENT 
    -- here put WHERE with filtering conditions for PROCESSOR_EVENT table 
) pe 
    LEFT OUTER JOIN COMM_EVENT ce 
    ON ce.Machine = pe.Machine 
    AND ce.Time > pe.Time 
    AND (pe.next_pe_time IS NULL OR ce.Time < pe.next_pe_time) 
) t 
WHERE t.rn = 1 
ORDER BY t.Time 

測試它SQL Fiddle

+0

嗯,看起來很有希望,但我得到這個錯誤: ORA-01799:一列可能不是外部連接到子查詢 01799. 00000 - 「列可能不是外部連接到子查詢」 – 2014-10-10 08:36:40

+1

@RichardMaguire看到重寫的查詢它按預期工作 – Rimas 2014-10-10 12:17:51

+0

感謝@Rimas我接近讓它運行我認爲。 我不確定,但是您的JOIN的語法Oracle友好嗎?我必須將「LEFT JOIN」改爲「LEFT OUTER JOIN」,否則會崩潰。但我不確定要將「JOIN」(第18行)變成什麼? 最後,PROCESSOR_EVENT和COMM_EVENT的大小非常大,如果我只想查詢特定日期和時間範圍之間的結果,那麼我會在哪裏插入該限制條件? – 2014-10-11 08:02:10

0

有多種方法可以解決這個問題。在完成兩個表的結合之後,這是一種多次使用lead()的方法。基本數據是:

select pc.*, 
     lead(time) over (partition by machine order by time) as nexttime, 
     lead(which) over (partition by machine order by time) as nextwhich, 
     lead(type) over (partition by machine order by time) as nexttype 
from (select pe.time, pe.machine, pe.machine, pe.name, 'pe' as which 
     from processor_event pe 
     union all 
     select ce.time, ce.machine, ce.name, 'ce' as which 
     from comm_event ce 
    ) pc; 

接下來,我們只需要申請要這個數據的邏輯:

with pc as (
     select pc.*, 
      lead(time) over (partition by machine order by time) as nexttime, 
      lead(which) over (partition by machine order by time) as nextwhich, 
      lead(type) over (partition by machine order by time) as nexttype 
     from (select pe.time, pe.machine, pe.name, NULL as type, 'pe' as which 
      from processor_event pe 
      union all 
      select ce.time, ce.machine, ce.name, ce.type, 'ce' as which 
      from comm_event ce 
      ) pc 
    ) 
select pc.time, pc.machine, pc.name, 
     (case when nextwhich = 'ce' then nexttime end) as comm_time, 
     (case when nextwhich = 'ce' then nexttype end) as comm_type, 
     ((case when nextwhich = 'ce' then nexttime end) - time) as diff 
from pc 
where pc.which = 'pe'; 
+0

Woah,我還沒有做過之前升級過的SQL。這全是1個查詢嗎? – 2014-10-10 08:05:57

+0

@Richard Maguire:是的,有一個問題。從SELECT開始並以分號結尾的第一個查詢是基本語句。只是爲了說明。執行它以查看LEAD和UNION ALL的功能。真正的查詢包含這個基本語句。它以WITH開頭並以分號結尾。 – 2014-10-10 08:12:21

+0

好的,謝謝Thorsten。我嘗試執行第一個查詢,但得到錯誤: ORA-00904:「TYPE」:無效的標識符 00904. 00000 - 「%s:無效的標識符」 錯誤在行:4列:12 – 2014-10-10 08:46:01