我将一些日内库存数据保存到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
当然这个查询不起作用,但它应该是这样的。
如果没有游标和临时表,我会很感激如何解决这个问题。
答案 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
它确实使用临时表(确保它是速度的内存表),但它不需要游标。