插值MySQL表中的缺失值

时间:2011-09-04 13:07:46

标签: 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

当然这个查询不起作用,但它应该是这样的。

如果没有游标和临时表,我会很感激如何解决这个问题。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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中的所有数据,然后从结果中选择所需的行。

答案 2 :(得分: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)  

使用临时值更新库存表

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

它确实使用临时表(确保它是速度的内存表),但它不需要游标。