使用 MySQL 或 H2 将空值替换为列中的最新值
Replace null values with the latest value in a column using MySQL or H2
提出了同样的问题,但是所提供的所有答案都是针对 SQL 服务器 2008 的,并且这些方法都不适用于 MySQL 或 H2:
replace NULL values with latest non-NULL value in resultset series (SQL Server 2008 R2)
类似问题(还有 SQL 服务器 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);
请保持简单。
如果你有 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
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<>fiddle here
我理解这个问题是为了更新 table 数据,一个产品的价格不应该影响另一个产品的价格。看起来像这样:
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;
如果目标只是在 select 期间用之前的值替换空值,这可以使用 window 函数轻松实现,除了 mysql 和 mariadb 还没有实施了 LAG() IGNORE NULLS 函数 :( 因此它需要使用变量(参见 nbk 的回答)或 self-join:
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;
分组依据是必需的,但会删除重复的条目;按主键分组会更好。
提出了同样的问题,但是所提供的所有答案都是针对 SQL 服务器 2008 的,并且这些方法都不适用于 MySQL 或 H2:
replace NULL values with latest non-NULL value in resultset series (SQL Server 2008 R2)
类似问题(还有 SQL 服务器 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);
请保持简单。
如果你有 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
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<>fiddle here
我理解这个问题是为了更新 table 数据,一个产品的价格不应该影响另一个产品的价格。看起来像这样:
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;
如果目标只是在 select 期间用之前的值替换空值,这可以使用 window 函数轻松实现,除了 mysql 和 mariadb 还没有实施了 LAG() IGNORE NULLS 函数 :( 因此它需要使用变量(参见 nbk 的回答)或 self-join:
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;
分组依据是必需的,但会删除重复的条目;按主键分组会更好。