2011-09-04 108 views
4

我已經保存到MySQL表看起來像這樣一些盤中個股數據:在MySQL表中插入丟失的值

+----------+-------+ 
| tick  | quote | 
+----------+-------+ 
| 08:00:10 | 5778 | 
| 08:00:11 | 5776 | 
| 08:00:12 | 5778 | 
| 08:00:13 | 5778 | 
| 08:00:14 | NULL | 
| 08:00:15 | NULL | 
| 08:00:16 | 5779 | 
| 08:00:17 | 5778 | 
| 08:00:18 | 5780 | 
| 08:00:19 | NULL | 
| 08:00:20 | 5781 | 
| 08:00:21 | 5779 | 
| 08:00:22 | 5779 | 
| 08:00:23 | 5779 | 
| 08:00:24 | 5778 | 
| 08:00:25 | 5779 | 
| 08:00:26 | 5777 | 
| 08:00:27 | NULL | 
| 08:00:28 | NULL | 
| 08:00:29 | 5776 | 
+----------+-------+ 

正如你所看到的,也有一些點沒有數據可用(報價NULL)。我想要做的是一個簡單的步驟插值。這意味着每個NULL值應該用最後一個可用值進行更新。我設法做到這一點的唯一方法是使用遊標,由於大量的數據,遊標速度很慢。我基本上尋找這樣的事情:

UPDATE table AS t1 
SET quote = (SELECT quote FROM table AS t2 
      WHERE t2.tick < t1.tick AND 
        t2.quote IS NOT NULL 
      ORDER BY t2.tick DESC 
      LIMIT 1) 
WHERE quote IS NULL 

當然,這種查詢是行不通的,但是這是應該的樣子。

我希望這是如何能夠在不遊標和臨時表來解決任何想法。

+1

有沒有在這個仔細地看了看,但爲什麼不是查詢工作?如果僅僅是因爲你得到'你無法指定目標表...在FROM子句中更新'的錯誤,那麼[在這裏]的解決方法是(http://www.xaprb.com/blog/2006/ 06/23 /如何選擇從更新目標在MySQL /) –

+1

@馬丁史密斯這裏不是那麼容易。在子查詢中你可以引用主查詢't2.tick

+0

@Kamil - 對啊,我明白了。在類似'row_number'模擬技術的MySQL的更新語句中,是否有任何方式使用用戶變量? –

回答

5

這應該工作:

SET @prev = NULL; 

UPDATE ticks 
SET  quote= @prev := coalesce(quote, @prev) 
ORDER BY tick; 

BTW同樣的伎倆適用於閱讀:

SELECT t.tick, @prev := coalesce(t.quote, @prev) 
FROM  ticks t 
JOIN  (SELECT @prev:=NULL) as x -- initializes @prev 
ORDER BY tick 
+0

+1在評論中如果有這樣的事情是可能的話,難道不知道嗎? –

+0

@arnaud +1,但是你不是插值的,你正在重複之前的值,你需要用平均值(@ prev,@ next)來更新! – Johan

0

這裏的主要問題是參照主查詢中子查詢t2.tick < t1.tick。因此,您不能簡單地將子查詢包裝在另一個子查詢中。

如果這是一次查詢並沒有這麼多的數據,你可以做這樣的事情:

UPDATE `table` AS t1 
SET quote = (SELECT quote FROM (SELECT quote, tick FROM `table` AS t2 WHERE t2.quote IS NOT NULL) as t3 WHERE t3.tick < t1.tick ORDER BY t3.tick DESC LIMIT 1) 
WHERE quote IS NULL 

不過說真的,真的不使用,因爲它很可能是緩慢。在每個空引用上,該查詢選擇表table中的所有數據,然後從結果中獲得所需的行。

0

我想創建一個(臨時)表相同的佈局爲你的表和運行以下兩個查詢:

將所有插值插入到temp_stock表中

INSERT INTO temp_stock (tick, quote) 
    SELECT s2.tick 
     , (s1.quote + s3.quote) /2 as quote 
    FROM stock 
    INNER JOIN stock s1 ON (s1.tick < s2.tick) 
    INNER JOIN stock s3 ON (s3.tick > s2.tick) 
    WHERE s2.quote IS NULL 
    GROUP BY s2.tick 
    HAVING s1.tick = MAX(s1.tick), s3.tick = MIN(s3.tick) 

更新庫存表Temp值

UPDATE stock s 
    INNER JOIN temp_stock ts ON (ts.tick = s.tick) SET s.quote = ts.quote 

它確實使用臨時表(請確保它是速度的內存表),但它並不需要使用遊標。