检查null并替换最近的非null值

时间:2014-11-12 20:43:02

标签: sql sql-server sql-server-2008

Query需要检查空值并替换为最近的非空值。

例如,考虑下面提供的源数据。

查询需要检查空值并在第二行找到它,现在它应该用最近的非空数据替换空值,数据是“colmin”。

同样,Query需要检查空值,现在它在第三行中找到它,然后它将使用最近的非空数据进行更新,并且数据再次是“colmin”。

提前致谢!

输入

source data    
Colmin    
NULL
NULL
NULL
NULL
columnxy
column99
NULL
NULL
money
NULL
NULL
NULL
start end
NULL

所以输出应该是......

输出

Ouput data
Colmin    
Colmin    
Colmin    
Colmin    
Colmin    
Colmin    
columnxy
column99
column99
column99
money
money
money
money
start end
start end

3 个答案:

答案 0 :(得分:1)

什么是最近的" ?我希望你有一些领域要分类。行号不能总是正确的顺序!虽然我会使用orderField来确定行顺序。

UPDATE myTable
SET a = (
    SELECT a
    FROM myTable
    WHERE a IS NOT NULL
    AND orderField > (
      SELECT orderField
      FROM myTable
      WHERE a IS NULL
      ORDER BY orderField
      LIMIT 1
    )
    ORDER BY orderField
    LIMIT 1
  )
WHERE a IS NULL
ORDER BY orderField
像这样的事情应该这样做......我希望。它没有经过考验。

它的作用:

  1. 查找" orderField"对于第一行,其中a = null
  2. 1.
  3. 之后的orderField之后首先找到一个值(!= null)
  4. 使用1.
  5. 的值更新2.的值

    它也应该更容易:

    UPDATE myTable t1
    SET t1.a = (
        SELECT t2.a
        FROM myTable t2
        WHERE t2.a IS NOT NULL
        AND t2.orderField > t1.orderField
        ORDER BY t2.orderField
        LIMIT 1
      )
    WHERE t1.a IS NULL
    

答案 1 :(得分:0)

如果您的表是单列,那么您将需要在循环中运行多个查询或使用游标迭代遍历表,一次一行。 (效率不高。)

如果您有某种ID列,则可以使用相关子查询来查找第一个非空值。有点像...

Update A
Set    TextCol = (SELECT Top 1 TextCol From MyTable B Where B.TextCol IS NOT NULL AND B.IDCol < A.IDCol ORDER BY IDCol DESC)
FROM   MyTable A
WHERE  TextCol IS NULL

答案 2 :(得分:0)

试试这个:

declare @input table (id bigint not null identity(1,1), OutputData nvarchar(16) null)
insert @input select 'Colmin'    
insert @input select NULL
insert @input select NULL
insert @input select NULL
insert @input select NULL
insert @input select 'columnxy'
insert @input select 'column99'
insert @input select NULL
insert @input select NULL
insert @input select 'money'
insert @input select NULL
insert @input select NULL
insert @input select NULL
insert @input select 'start end'
insert @input select NULL

--where a's value is null, replace with a non-null from b
select coalesce(a.OutputData, b.OutputData) 
--return all rows from input as a
from @input a
--return all non-null values as b
left outer join
(
    select id, OutputData
    from @input
    where OutputData is not null
) b
--the non-null value should come before the null value (< or <= works equally here)
on b.id <= a.id
--and there shouldn't be a non-null value between b and a's records (i.e. b is the most recent before a)
and not exists (
    select top 1 1 
    from @input c 
    where c.id between b.id and a.id 
    and c.id <> b.id
    and c.OutputData is not null
)
--display the output in the required order
order by a.id