我有以下mysql表
+---------------------+------+
| time | val |
+---------------------+------+
| 2005-02-03 00:00:00 | 2.11 |
| 2005-02-04 00:00:00 | 2.11 |
| 2005-02-05 00:00:00 | NULL |
| 2005-02-06 00:00:00 | NULL |
| 2005-02-07 00:00:00 | 3.43 |
| 2005-02-08 00:00:00 | NULL |
| 2005-02-09 00:00:00 | NULL |
| 2005-02-10 00:00:00 | 5.66 |
| 2005-02-11 00:00:00 | 5.66 |
| 2005-02-12 00:00:00 | NULL |
+---------------------+------+
我想创建一个算法(在PHP中),根据最后一个非空值填充NULL值。因此该表将成为以下
+---------------------+------+
| time | val |
+---------------------+------+
| 2005-02-03 00:00:00 | 2.11 |
| 2005-02-04 00:00:00 | 2.11 |
| 2005-02-05 00:00:00 |>2.11 |
| 2005-02-06 00:00:00 |>2.11 |
| 2005-02-07 00:00:00 | 3.43 |
| 2005-02-08 00:00:00 |>3.43 |
| 2005-02-09 00:00:00 |>3.43 |
| 2005-02-10 00:00:00 | 5.66 |
| 2005-02-11 00:00:00 | 5.66 |
| 2005-02-12 00:00:00 |>5.66 |
+---------------------+------+
我正在寻找如何处理这种情况的线索。我正在使用PHP-Laravel。
这里有'{3}}'标准'SQL。
答案 0 :(得分:6)
正如评论所示,您应该在填充表时修复此问题。也就是说,它可以在PHP或MySQL中完成。这是一个选项:
SET @x:=0;
SELECT `time`, IF(val IS NOT NULL, @x:=val, @x) AS val
FROM yourtable
ORDER BY `time`;
请记住,您的结果会因订单和WHERE
等而发生变化。使用SET @x:=0;
为第一行的值NULL
时的案例定义默认值。
如果您需要永久修复数据,而不是单个查询,则可以使用“正确”值更新表格:
SET @x:=0;
UPDATE yourtable SET val=IF(val IS NOT NULL, @x:=val, @x)
ORDER BY `time`;
答案 1 :(得分:3)
如果您只想使用SQL,可以使用此UPDATE查询:
UPDATE
tab INNER JOIN (
SELECT
t1.time,
MAX(t2.time) prev_time
FROM
tab t1 INNER JOIN tab t2
ON t1.time>t2.time
WHERE
t1.val IS NULL
AND t2.val IS NOT NULL
GROUP BY
t1.time
) p ON tab.time = p.time
INNER JOIN tab t2 ON p.prev_time = t2.time
SET
tab.val = t2.val
请查看小提琴here。
对于每个NULL行,子查询将返回具有非NULL值的上一个日期。然后我自己加入表来获取值并更新空行。