SQL-用先前的值填充NULL值

时间:2019-05-26 19:47:42

标签: sql

在看到许多示例之后,我没有找到一种简单的方法来用最后一个值替换每列的NULL值。

旋转表之后,我有以下示例:

IDS 1234,4567,7890

| 1234     |   4567    |   7890  |
|  1       |    2      |    3    |
| NULL     |    4      |    5    |
| NULL     |    6      |   NULL  |
|  8       |   NULL    |    9    |

结果:

| 1234      |      4567      |     7890 |
|  1        |       2        |       3  |
|  1        |       4        |       5  |
|  1        |       6        |       5  |
|  8        |       6        |       9  |

2 个答案:

答案 0 :(得分:1)

我们不知道您的DBMS,但是对于大多数DBMS,lag()窗口分析函数用于以前的记录,而coalesce()函数用于替代空值。因此,尝试使用:

with t1( id, col_1234, col_4567, col_7890 ) as
(
  select 1, 1   , 2  , 3    union all
  select 2, NULL, 4  , 5    union all
  select 3, NULL, 6  , NULL union all
  select 4, 8   ,NULL, 9 
), t2 as
(
 select id,
        coalesce( col_1234, lag(col_1234) over (order by id) ) as col_1234,
        coalesce( col_4567, lag(col_4567) over (order by id) ) as col_4567,
        coalesce( col_7890, lag(col_7890) over (order by id) ) as col_7890
   from t1
)  
select coalesce( col_1234, lag(col_1234) over (order by id) ) as col_1234,
       col_4567, col_7890
  from t2

Demo

答案 1 :(得分:1)

使用CURSOR是因为结果集中有超过2个连续的NULL的可能性,并且LEAD和LAG方法将无法工作,因为它们只能检查1行。

DECLARE @id INT,@col_1234 INT, @col_4567 INT,@col_7890 INT
DECLARE @id_prev INT,@col_1234_prev INT,@col_4567_prev INT,@col_7890_prev INT
DECLARE @LoopOne INT = 1

DECLARE @TempTable TABLE
(
    id INT, col_1234 INT, col_4567 INT, col_7890 INT
)

DECLARE db_cursor CURSOR FOR 
SELECT id, col_1234, col_4567, col_7890 
FROM your_table

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @id, @col_1234, @col_4567, @col_7890 

WHILE @@FETCH_STATUS = 0  
BEGIN  

    IF @LoopOne = 1
    BEGIN
        SET @id_prev = @id
        SET @col_1234_prev = @col_1234
        SET @col_4567_prev = @col_4567
        SET @col_7890_prev = @col_7890

        INSERT INTO @TempTable(id, col_1234, col_4567, col_7890)
        VALUES (@id, @col_1234, @col_4567, @col_7890 )

        SET @LoopOne = 2
    END

    ELSE
    BEGIN
        SET @id_prev = CASE WHEN @id IS NULL THEN @id_prev ELSE @id END
        SET @col_1234_prev = CASE WHEN @col_1234 IS NULL THEN @col_1234_prev ELSE @col_1234 END
        SET @col_4567_prev = CASE WHEN @col_4567 IS NULL THEN @col_4567_prev ELSE @col_4567 END
        SET @col_7890_prev = CASE WHEN @col_7890 IS NULL THEN @col_7890_prev ELSE @col_7890 END

        INSERT INTO @TempTable(id, col_1234, col_4567, col_7890)
        VALUES (@id_prev, @col_1234_prev, @col_4567_prev, @col_7890_prev )
    END


    FETCH NEXT FROM db_cursor INTO @id, @col_1234, @col_4567, @col_7890 
END 

CLOSE db_cursor  
DEALLOCATE db_cursor 

SELECT * FROM @TempTable