2012-02-18 90 views
0

我有高頻率刻度數據,需要從微秒到6秒的時間間隔進行排序。每日報價數據從美國東部時間09:15:00.000開始,到美國東部時間15:15:00,000結束。使用Oracle,從微秒到6秒的時間間隔

這是我temp2表:

date1      | close1 | volume1 
-----------------------------+--------+--------- 
2010-04-16 09:15:28.010 EST | 10001 |  4 
2010-04-16 09:16:00.020 EST | 10002 |  5 
2010-04-16 09:16:35.030 EST | 10003 |  6 
2010-04-16 09:16:35.040 EST | 10001 |  3 
2010-04-16 15:14:59.050 EST | 10007 |  3 
2010-04-19 09:15:05.050 EST | 10002 |  1 
...       | ... |  ... 

date1VARCHAR2(28); close1volume1都是NUMBER S)。

如何獲得以下結果?

date2    | close2 | volume2 
---------------------+--------+--------- 
2010-04-16 09:15:30 | 10001 |  4 
2010-04-16 09:16:06 | 10002 |  5 
2010-04-16 09:16:36 | 10001 |  9 
2010-04-16 15:15:00 | 10007 |  3 
2010-04-19 09:15:06 | 10002 |  1 
...     | ... |  ... 

的間隔00,06,12,18,24,30,36,42,48,54,並且如果在範圍內微秒close2柱使用LAST_VALUE 00-05.999,只需設置close2列值作爲last_vlue的間隔,設置volume2列值爲總和volume1的區間。

+2

我不明白您的輸入數據與您的輸出之間的關係;你能詳細解釋一下嗎? – ruakh 2012-02-18 14:09:27

+1

如果您要存儲時間戳,然後將它們存儲在'timestamp'數據類型中,那麼在此之後排序很容易... – Ben 2012-02-18 14:25:00

+0

@ruakh:close2列使用間隔爲00,06,12,18,24,30,36,38的last_value,如果在00-05.999範圍內有微秒,只需將close2列值設置爲區間的last_vlue,則將volume2列值設置爲區間的volume1之和。 – 2012-02-18 14:48:42

回答

0

而不是包裝所有的邏輯到一個查詢—這是可能的,但令人難以置信的醜陋和痛苦的—我覺得很有道理創建一個存儲過程即會將您date1date2

CREATE OR REPLACE FUNCTION date1_to_date2 (date1 IN VARCHAR2) RETURN varchar2 
IS 

    ts TIMESTAMP; 

BEGIN 

    ts := TO_TIMESTAMP(SUBSTR(date1, 1, 19), 'YYYY-MM-DD HH24:MI:SS'); 

    IF SUBSTR(date1, 21, 3) > 0 THEN 
    ts := ts + NUMTODSINTERVAL(1, 'SECOND'); 
    END IF; 

    ts := ts + NUMTODSINTERVAL(MOD(60 - TO_CHAR(ts, 'SS'), 6), 'SECOND'); 

    RETURN TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS'); 

END date1_to_date2; 
/

SHOW ERRORS; 

然後休息,而不是完全明瞭,仍然是可口:

SELECT date2, 
     close1 AS close2, 
     volume2 
    FROM (SELECT date2, 
       close1, 
       ROW_NUMBER() OVER (PARTITION BY date2 ORDER BY date1 DESC) AS rn, 
       SUM(volume1) OVER (PARTITION BY date2) AS volume2 
      FROM (SELECT date1, 
         date1_to_date2(date1) AS date2, 
         close1, 
         volume1 
        FROM temp2 
       ) 
     ) 
WHERE rn = 1 
ORDER BY date2 
; 

(實際上,你可以只用一個子查詢做到這一點,通過替換defin即使沒有任何的子查詢date2到處—,也許銀行足球比賽可言,如果WHERE rn = 1可以轉換成一個HAVING條款,我沒有嘗試—但我認爲這是最清楚的方式。)

+0

感謝您的幫助,Rurkh,您所修改的問題內容的新安排非常整齊美觀。而你的傑出作品爲我提供了甲骨文的一個全新的深層次方面。 – 2012-02-20 01:07:24

2

問題的核心是將你有的時間戳轉換成對應於你的6秒間隔的「桶」。一種方法是將日期的部分提取到分鐘,這可以使用TRUNC函數完成,秒數作爲單獨的值來完成。 (請注意,我治療date1,如果它已經是一個TIMESTAMP,作爲評價和回答你的問題之前的推薦,但如果它保持爲VARCHAR,那麼你就需要將其轉換):

select trunc(date1, 'MI'), extract(second from date1) from temp2; 

2010-04-16 09:15:00 28.01 
2010-04-16 09:16:00  .02 
2010-04-16 09:16:00 35.03 
2010-04-16 09:16:00 35.04 
2010-04-16 15:14:00 59.05 
2010-04-19 09:15:00 5.05 

...然後操縱秒部得到它圓了你的窗口:

select trunc(date1, 'MI'), 
    6 * (trunc(1 + extract(second from date1)/6)) 
from temp2; 

2010-04-16 09:15:00 30.00 
2010-04-16 09:16:00 6.00 
2010-04-16 09:16:00 36.00 
2010-04-16 09:16:00 36.00 
2010-04-16 15:14:00 60.00 
2010-04-19 09:15:00 6.00 

...最後加在一起,跳水「秒」窗口中做日期計算86400,一天中的秒數:

select trunc(date1,'MI') 
    + (6 * trunc(1 + (extract(second from date1)/6)))/(24*60*60) 
from temp2; 

...和你再乘以分,這可以稍微降低到:

select trunc(date1,'MI') 
    + trunc(1 + (extract(second from date1)/6))/(24*60*10) 
from temp2; 

2010-04-16 09:15:30 
2010-04-16 09:16:06 
2010-04-16 09:16:36 
2010-04-16 09:16:36 
2010-04-16 15:15:00 
2010-04-19 09:15:06 

現在你可以使用這個爲基礎,一些analytic functions獲得所需要的價值爲其他領域,是這樣的:

select distinct date2, 
    first_value(close1) over (partition by date2 order by date1 desc) as close2, 
    sum(volume1) over (partition by date2) as volume2 
from (
    select date1, close1, volume1, trunc(date1,'MI') 
     + trunc(1 + (extract(second from date1)/6))/(24*60*10) as date2 
    from temp2 
) 
order by date2, close2, volume2; 

DATE2     CLOSE2 VOLUME2 
------------------- ---------- ---------- 
2010-04-16 09:15:30  10001   4 
2010-04-16 09:16:06  10002   5 
2010-04-16 09:16:36  10001   9 
2010-04-16 15:15:00  10007   3 
2010-04-19 09:15:06  10002   1 

我固定該日期的間隔版本到現有列,使整個事情的內嵌視圖,因爲我們需要所有的原始列過;併爲每個date2我使用FIRST_VALUE函數(在排序中使用desc)和SUM的分析版本獲取最新的close1值,以獲得該窗口的總計volume1distinct在那裏,因爲anayltics爲09:16:36兩行提供了相同的值,但在這種情況下你只需要其中的一個。

+0

你是如此的才華和聰明,Thnaks你的熱心幫助。一個很好的解決方案。 – 2012-02-20 01:02:33

+0

亞歷克斯普爾,我的兩個問題是由你和另一位專家解決的,現在我有多開心。謝謝你花這麼多時間來研究我的問題。來自我的問候。 – 2012-02-20 01:12:50

+0

有趣。我第一次聽說過「提取」功能。 – Gerrat 2015-01-12 15:27:40