2012-11-29 20 views
0

我有一個表看起來像這樣:MySQL的:時間戳行之間轉移數據

mysql> explain test_table; 
+---------------------+-------------+------+-----+---------+-------+ 
| Field    | Type  | Null | Key | Default | Extra | 
+---------------------+-------------+------+-----+---------+-------+ 
| timestamp   | datetime | NO | PRI | NULL |  | 
| id     | varchar(64) | NO | PRI | NULL |  | 
| px_last    | float  | NO |  | NULL |  | 
| twap    | float  | YES |  | NULL |  | 
+---------------------+-------------+------+-----+---------+-------+ 

對於給定的符號和時間戳,我要到外地twap的值一個時步移回。

該表:

mysql> select * from test_table; 
+---------------------+-------+---------+-------+ 
| timestamp   | id | px_last | twap | 
+---------------------+-------+---------+-------+ 
| 2011-01-01 00:00:00 | apple |  101 | 101.1 | 
| 2011-01-01 00:00:00 | pear |  50 | 50.1 | 
| 2011-01-02 00:00:00 | apple |  102 | 112.8 | 
| 2011-01-02 00:00:00 | pear |  51 | 57.3 | 
| 2011-01-03 00:00:00 | pear |  52 | 59.1 | 
| 2011-01-03 00:00:00 | apple |  103 | 104.1 | 
+---------------------+-------+---------+-------+ 

應該結束了這樣的:

mysql> select * from test_table; 
+---------------------+-------+---------+-------+ 
| timestamp   | id | px_last | twap | 
+---------------------+-------+---------+-------+ 
| 2011-01-01 00:00:00 | apple |  101 | 112.8 | 
| 2011-01-01 00:00:00 | pear |  50 | 57.3 | 
| 2011-01-02 00:00:00 | apple |  102 | 104.1 | 
| 2011-01-02 00:00:00 | pear |  51 | 59.1 | 
| 2011-01-03 00:00:00 | pear |  52 | NULL | 
| 2011-01-03 00:00:00 | apple |  103 | NULL | 
+---------------------+-------+---------+-------+ 

我的第一種方法(使用本例中:How to number rows...)是創建一個行號(1,2 .. ..n),然後將行號,符號和twap複製到臨時表中,在臨時表的每一行中將行號減1,然後將數據複製回原始表。

有沒有辦法做到這一點,而不創建臨時表?這個表格非常龐大,超過5000萬行並且不斷增長,因此找到比給定時間戳更小的最大時間戳記效率不夠高。

回答

1

你可以寫:

UPDATE test_table tt1 
    SET tt1.twap = 
     (SELECT tt2.twap 
      FROM (SELECT timestamp, 
          id, 
          twap 
        FROM test_table 
       ) tt2 
      WHERE tt2.timestamp = DATE_ADD(tt1.timestamp, INTERVAL 1 DAY) 
      AND tt2.id = tt1.id 
     ) 
; 

從技術上講,這創建臨時表(到可怕的ERROR 1093 (HY000): You can't specify target table 'tt1' for update in FROM clause解決方法),但至少這一切都通過內部子隱式地處理,而不是要求你創建一個單獨的步驟。

對於一個大型表格,我不希望它表現得很好,但您可以通過一次只處理一個時間範圍將它分解爲更小的更新(只要您從最早的時間範圍開始並向前移動,這樣你就不會覆蓋你即將使用的數據)。您的個人陳述將看起來像這樣:

UPDATE test_table tt1 
    SET tt1.twap = 
     (SELECT tt2.twap 
      FROM (SELECT timestamp, 
          id, 
          twap 
        FROM test_table 
        WHERE timestamp BETWEEN TIMESTAMP '2011-01-02 00:00:00' 
             AND TIMESTAMP '2011-02-01 23:59:59' 
       ) tt2 
      WHERE tt2.timestamp = DATE_ADD(tt1.timestamp, INTERVAL 1 DAY) 
      AND tt2.id = tt1.id 
     ) 
    WHERE tt1.timestamp BETWEEN TIMESTAMP '2011-01-01 00:00:00' 
          AND TIMESTAMP '2011-01-31 23:59:59' 
; 
+0

感謝您的更正和建議!但是,間隔有時會超過一天(假期等),在這種情況下,我希望您的解決方案發生故障,對吧? – mxns

+0

@MånsRolandiDanielsson:是的,這個解決方案要求連續幾天。 – ruakh