繁体   English   中英

根据“最接近”匹配的“早期”行替换当前行中的NULL值。 (基于日期的表格)

[英]Replacing NULL value in current row based on 'closest' matching 'earlier' row. (date based table)

我有以下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。

这里有一个SQLFiddle用于'标准'SQL。

正如评论所示,您应该在填充表时修复此问题。 也就是说,它可以在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`;

如果您只想使用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

在这里看一个小提琴。

对于每个NULL行,子查询将返回具有非NULL值的上一个日期。 然后我自己加入表来获取值并更新空行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM