SQL QUERY使用前一个已知值的值replace行中的NULL值

我有2列

date number ---- ------ 1 3 2 NULL 3 5 4 NULL 5 NULL 6 2 ....... 

我需要用新的值replaceNULL值取自date列中前一个date的最后一个已知值的值,例如:date = 2 number = 3,date 4和5 number = 5和5.出现NULL值随机。

如果你正在使用Sql Server,这应该工作

 DECLARE @Table TABLE( ID INT, Val INT ) INSERT INTO @Table (ID,Val) SELECT 1, 3 INSERT INTO @Table (ID,Val) SELECT 2, NULL INSERT INTO @Table (ID,Val) SELECT 3, 5 INSERT INTO @Table (ID,Val) SELECT 4, NULL INSERT INTO @Table (ID,Val) SELECT 5, NULL INSERT INTO @Table (ID,Val) SELECT 6, 2 SELECT *, ISNULL(Val, (SELECT TOP 1 Val FROM @Table WHERE ID < t.ID AND Val IS NOT NULL ORDER BY ID DESC)) FROM @Table t 

这是一个MySQL解决scheme:

 UPDATE mytable SET number = (@n := COALESCE(number, @n)) ORDER BY date; 

这是简洁的,但不会在其他品牌的RDBMS工作。 对于其他品牌,可能会有更具针对性的品牌特定解决scheme。 这就是为什么告诉我们你使用的品牌很重要。

像@Pax评论的那样,独立于供应商是很好的,但如果不这样做,那么使用您select的数据库品牌也是非常好的。


上述查询的解释:

@n是一个MySQL用户variables。 它从NULL开始,并在UPDATE在行中运行时在每行上分配一个值。 其中number是非NULL,@n被赋值为number的值。 如果number是NULL,则COALESCE()默认为@n的前一个值。 在任何一种情况下,这都会成为number列的新值,UPDATE会继续到下一行。 @nvariables在行之间保留它的值,所以后面的行得到来自前一行的值。 UPDATE的顺序是可以预测的,因为MySQL特别使用ORDER BY和UPDATE(这不是标准的SQL)。

最好的解决scheme是Bill Karwin提供的解决scheme。 我最近不得不用一个相对较大的结果集来解决这个问题(1000行,每行12列,如果这个值在当前行为null,则需要显示最后一个非空值),并使用top 1的update方法select以前已知的值(或顶部1的子查询)运行速度超慢。

我正在使用SQL 2005和variablesreplace语法略有不同于MySQL:

 UPDATE mytable SET @n = COALESCE(number, @n), number = COALESCE(number, @n) ORDER BY date 

如果'number'不是null(COALESCE返回你传入的第一个非null参数),第一个set语句将variables@n的值更新为当前行的'number'值第二个set语句更新实际(如果不为空)或variables@n(它始终包含遇到的最后一个非NULL值)的“number”列值。

这种方法的好处在于,不需要额外的资源来重复扫描临时表… @n的行内更新负责跟踪最后一个非空值。

我没有足够的代表投票答复,但有人应该。 这是最优雅和最好的表演。

这里是Oracle解决scheme(10g或更高版本)。

 SQL> select * 2 from mytable 3 order by id 4 / ID SOMECOL ---------- ---------- 1 3 2 3 5 4 5 6 2 6 rows selected. SQL> select id 2 , last_value(somecol ignore nulls) over (order by id) somecol 3 from mytable 4 / ID SOMECOL ---------- ---------- 1 3 2 3 3 5 4 5 5 5 6 2 6 rows selected. SQL> 

我知道这是一个非常古老的论坛,但是在解决我的问题的同时我遇到了这个问题:)刚刚意识到其他人已经给上述问题提供了一点复杂的解决scheme。 请参阅下面的解决scheme:

 DECLARE @A TABLE(ID INT, Val INT) INSERT INTO @A(ID,Val) SELECT 1, 3 INSERT INTO @A(ID,Val) SELECT 2, NULL INSERT INTO @A(ID,Val) SELECT 3, 5 INSERT INTO @A(ID,Val) SELECT 4, NULL INSERT INTO @A(ID,Val) SELECT 5, NULL INSERT INTO @A(ID,Val) SELECT 6, 2 UPDATE D SET D.VAL = E.VAL FROM (SELECT A.ID C_ID, MAX(B.ID) P_ID FROM @A AS A JOIN @A AS B ON A.ID > B.ID WHERE A.Val IS NULL AND B.Val IS NOT NULL GROUP BY A.ID) AS C JOIN @A AS D ON C.C_ID = D.ID JOIN @A AS E ON C.P_ID = E.ID SELECT * FROM @A 

希望这可能有助于某人:)

以下脚本解决了这个问题,只使用普通的ANSI SQL。 我在SQL2008 , SQLite3和Oracle11g上testing了这个解决scheme。

 CREATE TABLE test(mysequence INT, mynumber INT); INSERT INTO test VALUES(1, 3); INSERT INTO test VALUES(2, NULL); INSERT INTO test VALUES(3, 5); INSERT INTO test VALUES(4, NULL); INSERT INTO test VALUES(5, NULL); INSERT INTO test VALUES(6, 2); SELECT t1.mysequence, t1.mynumber AS ORIGINAL , ( SELECT t2.mynumber FROM test t2 WHERE t2.mysequence = ( SELECT MAX(t3.mysequence) FROM test t3 WHERE t3.mysequence <= t1.mysequence AND mynumber IS NOT NULL ) ) AS CALCULATED FROM test t1; 

从一般意义上说:

 UPDATE MyTable SET MyNullValue = MyDate WHERE MyNullValue IS NULL 

首先,你真的需要存储的价值? 你可以使用这个工作的观点:

 SELECT t."date", x."number" AS "number" FROM @Table t JOIN @Table x ON x."date" = (SELECT TOP 1 z."date" FROM @Table z WHERE z."date" <= t."date" AND z."number" IS NOT NULL ORDER BY z."date" DESC) 

如果你真的有ID ("date")列,它是一个主键(聚集),那么这个查询应该是非常快的。 但是检查查询计划:最好有一个包括Val列的封面索引。

另外,如果你不喜欢程序,当你可以避免它们,你也可以使用类似的查询UPDATE

 UPDATE t SET t."number" = x."number" FROM @Table t JOIN @Table x ON x."date" = (SELECT TOP 1 z."date" FROM @Table z WHERE z."date" < t."date" --//@note: < and not <= here, as = not required AND z."number" IS NOT NULL ORDER BY z."date" DESC) WHERE t."number" IS NULL 

注意:代码必须在“SQL Server”上工作。

这是MS Access的解决scheme。

示例表被称为tab ,带有字段idval

 SELECT (SELECT last(val) FROM tab AS temp WHERE tab.id >= temp.id AND temp.val IS NOT NULL) AS val2, * FROM tab; 
 UPDATE TABLE SET number = (SELECT MAX(t.number) FROM TABLE t WHERE t.number IS NOT NULL AND t.date < date) WHERE number IS NULL 

如果你正在寻找一个Redshift的解决scheme,这将适用于框架条款:

SELECT date,last_value(columnName ignore nulls)over(根据datesorting,在无界前面和当前行之间的行)作为columnName从tbl

尝试这个:

 update Projects set KickOffStatus=2 where KickOffStatus is null