Since you are on SQL Server 2012... here is a version that uses that. It might be faster than other solutions but you have to test that on your data.
sum() over()
will do a running sum ordered by Id
adding 1
when there are a value in the column and keeping the current value for null
values. The calculated running sum is then used to partition the result in first_value() over()
. The first value ordered by Id
for each "group" of rows generated by the running sum has the value you want.
select T.Id,
first_value(T.FeeModeId)
over(partition by T.NF
order by T.Id
rows between unbounded preceding and current row) as FeeModeId,
first_value(T.Name)
over(partition by T.NS
order by T.Id
rows between unbounded preceding and current row) as Name,
T.Amount
from (
select Id,
FeeModeId,
Name,
Amount,
sum(case when FeeModeId is null then 0 else 1 end)
over(order by Id) as NF,
sum(case when Name is null then 0 else 1 end)
over(order by Id) as NS
from YourTable
) as T
SQL Fiddle
Something that will work pre SQL Server 2012:
select T1.Id,
T3.FeeModeId,
T2.Name,
T1.Amount
from YourTable as T1
outer apply (select top(1) Name
from YourTable as T2
where T1.Id >= T2.Id and
T2.Name is not null
order by T2.Id desc) as T2
outer apply (select top(1) FeeModeId
from YourTable as T3
where T1.Id >= T3.Id and
T3.FeeModeId is not null
order by T3.Id desc) as T3
SQL Fiddle
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…