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

问题描述

问了同样的问题,但是提供的所有答案都是针对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),'2008-01-03','23'),'2008-01-04',NULL);

请保持简单。

解决方法

如果您使用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),'2008-01-01 12:02','2008-01-01 12:03','23.45'),'2008-01-01 12:04',NULL);
SELECT 
`product`,@price := IF(`price` IS NULL,@price,`price`) 'price'
FROM (SELECT * FROM table1 ORDER BY `timestamp`) t1,(SELECT @price := 0) t2
product | timestamp           | price
------: | :------------------ | :----
   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

,

我将这个问题理解为正在更新表格数据,并且一个产品的价格不应影响另一种产品的价格。看起来像这样:

set @price:=null,@product:=null;
update table1
    set price=if(price is not null,@price:=price,if(product=@product,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.price;

需要分组依据,但是将删除重复的条目;按主键分组会更好。