SQL根据以前的行填写空白数据

Sha*_*awn 3 sql sql-server loops sql-update

我有一个类似于以下的SQL表:

ID, Date,   D1, D2, D3
1   1/1/13  0   X   A
2   1/2/13          
3   1/3/13  1
4   1/4/13          B
5   1/5/13  
Run Code Online (Sandbox Code Playgroud)

我需要更新到以下内容:

ID, Date,   D1, D2, D3
1   1/1/13  0   X   A
2   1/2/13  0   X   A       
3   1/3/13  1   X   A   
4   1/4/13  1   X   B
5   1/5/13  1   X   B
Run Code Online (Sandbox Code Playgroud)

基本上用前面的值填充所有空值.这只会执行一次.循环是最好的选择吗?还是有更有效的东西?

Tim*_*ter 5

假设你正在使用SQL-Server,你可以使用这个common-table-expression:

WITH cte 
     AS (SELECT T1.id, 
                T1.date, 
                d1 = COALESCE(T1.d1, (SELECT TOP 1 d1 
                                      FROM   dbo.tablename T2 
                                      WHERE  T2.id < T1.id  
                                             AND d1 IS NOT NULL 
                                      ORDER  BY id DESC)), 
                d2 = COALESCE(T1.d2, (SELECT TOP 1 d2 
                                      FROM   dbo.tablename T2 
                                      WHERE  T2.id < T1.id 
                                             AND d2 IS NOT NULL 
                                      ORDER  BY id DESC)), 
                d3 = COALESCE(T1.d3, (SELECT TOP 1 d3 
                                      FROM   dbo.tablename T2 
                                      WHERE  T2.id < T1.id
                                             AND d3 IS NOT NULL 
                                      ORDER  BY id DESC)) 
         FROM   dbo.tablename T1) 
UPDATE T 
SET    T.d1 = C.d1, 
       T.d2 = C.d2, 
       T.d3 = C.d3 
FROM   dbo.tablename T 
       INNER JOIN cte C 
               ON T.id = C.id 
WHERE  T.d1 IS NULL 
        OR T.d2 IS NULL 
        OR T.d3 IS NULL 
Run Code Online (Sandbox Code Playgroud)

DEMO

编辑因为您在评论中提到过,''而不是null,这是一个支持两者的修改版本:

WITH cte AS 
        (SELECT T1.id, 
                T1.date, 
                d1 = CASE WHEN COALESCE(T1.d1, '') <> '' THEN d1 
                       ELSE(SELECT TOP 1 d1 
                            FROM   dbo.tablename T2 
                            WHERE  T2.id < T1.id 
                                   AND COALESCE(T2.d1, '') <> '' 
                            ORDER  BY T2.id DESC) END, 
                d2 = CASE WHEN COALESCE(T1.d2, '') <> '' THEN d2 
                       ELSE(SELECT TOP 1 d2 
                            FROM   dbo.tablename T2 
                            WHERE  T2.id < T1.id 
                                   AND COALESCE(T2.d2, '') <> '' 
                            ORDER  BY T2.id DESC) END, 
                d3 = CASE WHEN COALESCE(T1.d3, '') <> '' THEN d3 
                       ELSE(SELECT TOP 1 d3 
                            FROM   dbo.tablename T2 
                            WHERE  T2.id < T1.id 
                                   AND COALESCE(T2.d3, '') <> '' 
                            ORDER  BY T2.id DESC) END 
         FROM   dbo.tablename T1) 
UPDATE T 
SET    T.d1 = C.d1, 
       T.d2 = C.d2, 
       T.d3 = C.d3 
FROM   dbo.tablename T 
       INNER JOIN cte C 
               ON T.id = C.id 
WHERE  COALESCE(T.d1, '') = '' 
        OR COALESCE(T.d2, '') = '' 
        OR COALESCE(T.d3, '') = '' 
Run Code Online (Sandbox Code Playgroud)

DEMO