对于不同的组,sql查询用来自下一个已知值的已知值替换空值

时间:2015-03-05 03:14:42

标签: sql sql-server

我有这个SQL表,如下所示:

customer   date   number       
---------  ----   ------
A           1      3           
A           2      NULL        
A           3      5           
A           4      NULL        
A           5      6
B           1      NULL
B           2      NULL
B           3      10

根据客户的说法,我希望添加一个额外的列number_NEW,它用下一个已知的按时间顺序排列的已知数字(由日期确定)替换NULL中的NULL(如果这是null):

customer   date   number     number_NEW  
---------  ----   ------     ----------
A           1      3         3  
A           2      NULL      5 
A           3      5         5  
A           4      NULL      6
A           5      6         6
B           1      NULL      10
B           2      NULL      10
B           3      10        10

我如何在SQL中解决这个问题?

非常感谢!

3 个答案:

答案 0 :(得分:1)

您可以使用APPLY

SELECT
    *,
    Number_NEW = ISNULL(t.Number, x.Number)
FROM Test t
OUTER APPLY(
    SELECT TOP 1 Number
    FROM Test
    WHERE
        Customer = t.Customer
        AND Date > t.Date
        AND Number IS NOT NULL
    ORDER BY Date
)x
ORDER BY t.Customer, t.Date

答案 1 :(得分:0)

您的样本数据未达标。

[date]列不清楚。为了安全起见,我使用了row_number,我认为这是必需的。

此外,我认为您的问题已经解决。我已经使用动态LEAD()的sql 2012编写了此脚本。

它不仅提供正确的输出,还描绘了LEAD()的动态使用。

Declare @t table(customer varchar(20),[date] int, number int)      
insert into @t values
('A', 1,3  )         
,('A',           2,      NULL)        
,('A',           3,      5    )       
,('A',           4,      NULL  )      
,('A',           5,      6)
,('B',           1,      NULL)
,('B',           2,      NULL)
,('B',           3,      10)
;WITH CTE
AS (
    SELECT *
        ,ROW_NUMBER() OVER (
            PARTITION BY customer ORDER BY [DATE]
            ) RN
    FROM @T
    )
--SELECT * FROM CTE
SELECT *
    ,IIF(number IS NULL, LEAD(number, (
                SELECT TOP 1 RN - A.RN
                FROM CTE
                WHERE customer = a.customer
                    AND RN > a.RN
                    AND number IS NOT NULL
                ORDER BY RN
                ), number) OVER (
            ORDER BY customer
                ,[date]
            ), number) number_NEW
FROM CTE A

答案 2 :(得分:0)

alter table T add number_NEW int null;

update T /* substitute table name here -- I realize that SQL Server allows aliases */
set number_NEW = 
    case
        when number is null
        then (
            select min(t2.number) /* do date and number always increase together? */
            from T as t2
            /* substitute full table name here as well */
            where t2.customer = T.customer and t2.date > T."date"
        )
        else number
    end
);

alter table T alter column number_NEW int not null;