使用 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);
产品 |时间戳 |价格 ------: | :----------------- | :---- 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.45SELECT `product` , `timestamp` , @price := IF(`price` IS NULL, @price,`price`) 'price' FROM (SELECT * FROM table1 ORDER BY `timestamp`) t1,(SELECT @price := 0) t2
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 以替换空字符串的空值