使用 MySQL 或 H2 将空值替换为列中的最新值

Posted

技术标签:

【中文标题】使用 MySQL 或 H2 将空值替换为列中的最新值【英文标题】:Replace null values with the latest value in a column using MySQL or H2 【发布时间】:2020-08-10 21:59:55 【问题描述】:

问了同样的问题,但是提供的所有答案都是针对 SQL Server 2008 的,并且这两种方法都不适用于 mysql 或 H2:

replace NULL values with latest non-NULL value in resultset series (SQL Server 2008 R2)

类似问题(也是 SQL Server 2008,我们不知道所有表)

Replace null value by latest value

我需要的是可以与 MySQL 或 H2 一起使用的东西

如果我们有

product timestamp          price 
------- ----------------   -----
   5678 2008-01-01         12.34
   5678 2008-01-02         NULL
   5678 2008-01-03         NULL
   5678 2008-01-03         23.45
   5678 2008-01-04         NULL

结果应该是

product timestamp          price 
------- ----------------   -----
   5678 2008-01-01         12.34
   5678 2008-01-02         12.34
   5678 2008-01-03         12.34
   5678 2008-01-03         23.45
   5678 2008-01-04         23.45

MySQL 代码:

CREATE TABLE `table1` (
  `product` int(11) NOT NULL,
  `timestamp` date NOT NULL,
  `price` decimal(10,0) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;



INSERT INTO `table1` (`product`, `timestamp`, `price`) VALUES
(5678, '2008-01-01', '12'),
(5678, '2008-01-02', NULL),
(5678, '2008-01-03', NULL),
(5678, '2008-01-03', '23'),
(5678, '2008-01-04', NULL);

请保持简单。

【问题讨论】:

table1没有主键吗? @ysth 我用 SQL 代码更新了一个问题来创建表 是的,我看到您的示例数据没有;你的真实用例真的没有主键吗? 请解释 pk 如何与最终解决方案相关,并使用 pk 提供答案 没有一个有点奇怪(事实上,mysql强迫你有一个,如果你没有,你会为你隐藏一个,所以你没有保存任何东西一) 【参考方案1】:

如果你有 mysql 6.x 你可以使用用户定义的变量

CREATE TABLE table1 (
  `product` INTEGER,
  `timestamp` DATETIME,
  `price` VARCHAR(5)
);

INSERT INTO table1
  (`product`, `timestamp`, `price`)
VALUES
  ('5678', '2008-01-01 12:00', '12.34'),
  ('5678', '2008-01-01 12:01', NULL),
  ('5678', '2008-01-01 12:02', NULL),
  ('5678', '2008-01-01 12:03', '23.45'),
  ('5678', '2008-01-01 12:04', NULL);
SELECT 
`product`
, `timestamp`
, @price := IF(`price` IS NULL, @price,`price`) 'price'
FROM (SELECT * FROM table1 ORDER BY `timestamp`) t1,(SELECT @price := 0) t2
产品 |时间戳 |价格 ------: | :----------------- | :---- 5678 | 2008-01-01 12:00:00 | 12.34 5678 | 2008-01-01 12:01:00 | 12.34 5678 | 2008-01-01 12:02:00 | 12.34 5678 | 2008-01-01 12:03:00 | 23.45 5678 | 2008-01-01 12:04:00 | 23.45

db小提琴here

【讨论】:

谢谢,在赞成/接受之前会仔细检查。 很确定包含产品意味着更新该产品的最新价格【参考方案2】:

我理解这个问题是为了更新表格数据,一个产品的价格不应该影响另一个产品的价格。看起来像这样:

set @price:=null, @product:=null;
update table1
    set price=if(price is not null,
        @price:=price,
        if(product=@product,@price,price)
    ),
    product=@product:=product
order by product, timestamp;

如果目标只是在选择期间将空值替换为先前的值,则可以使用窗口函数轻松完成,除了 mysql 和 mariadb 尚未实现 LAG() IGNORE NULLS 函数:( 所以它需要使用变量(参见 nbk 的答案)或自联接:

select t.product, t.timestamp, coalesce(t.price, substr(max(concat(t2.timestamp,t2.price)),length(t.timestamp)+1)) price
from table1 t
left join table1 t2 on t2.product=t.product and t2.timestamp < t.timestamp and t.price is null and t2.price is not null
group by t.product, t.timestamp, t.price;

group by 是必需的,但会删除重复的条目;按主键分组会更好。

【讨论】:

赞成,因为我不清楚有关无法更新表的详细信息,在 MySQL 中运行代码并且它有效。

以上是关于使用 MySQL 或 H2 将空值替换为列中的最新值的主要内容,如果未能解决你的问题,请参考以下文章

IOS,如何在数组中的 dic 中循环 dic 以替换空字符串的空值

将空值设置为缺失表字段的默认值

EXCEL这列中的空单元格为啥选“空值”定位不了?

Power Query / Power BI - 用另一列中的值替换空值

如何将空值存储为整数字段

将空值传递给 Python 中的存储过程