使用CTE或任何有效的递归填充计算

时间:2012-09-14 09:10:07

标签: sql-server-2008 tsql recursion ssis common-table-expression

请尽可能有效地解决这个问题(最好是CTE)。

enter image description here

所以......在所示的表中,“值”列中的红色单元格是已知值 突出显示的绿色是使用旁边显示的公式计算的值。 我试图看看CTE是否可行。

这就像最后一个已知值及其各自的间隔;下一个已知值和相应的间隔;以及计算该值的区间;所有用于查找值,然后实习将以相同的方式用于下一个未知值。

2 个答案:

答案 0 :(得分:2)

这是一个解决方案。

希望它有所帮助。 :)

;with testdata(store,shipntrvl,value)
as
(
select 'abc', 1, 0.56
union all
select 'abc', 5, null
union all
select 'abc', 10, 0.63
union all
select 'abc', 15, null
union all
select 'abc', 20, null
union all
select 'abc', 25, null
union all
select 'abc', 30, 0.96
union all
select 'xyz', 1, 0.36
union all
select 'xyz', 5, 0.38
union all
select 'xyz', 10, null
union all
select 'xyz', 15, 0.46
union all
select 'xyz', 20, null
union all
select 'xyz', 25, null
union all
select 'xyz', 30, 0.91
)
,calc
as
(
select  *
        ,ROW_NUMBER() OVER(partition by store order by shipntrvl) as row_no
from testdata
)
,extra
as
(
select  *
        ,(select    top 1 row_no 
          from      calc c2 
          where     c2.row_no < c1.row_no 
            and     c1.value is null 
            and     c2.value is not null 
            and     c1.store = c2.store 
          order by c2.row_no desc) as prev_nr
        ,(select    top 1 row_no 
          from      calc c2 
          where     c2.row_no > c1.row_no 
            and     c1.value is null 
            and     c2.value is not null 
            and     c1.store = c2.store 
          order by c2.row_no asc) as next_nr
from    calc c1
)

select  c.store
        ,c.shipntrvl
        ,c.value
        ,isnull(c.value, 
            (cnext.value-cprev.value)/
            (cnext.shipntrvl-cprev.shipntrvl)*
            (c.shipntrvl-cprev.shipntrvl)+cprev.value
        ) as calculated_value
from    calc c
join    extra
    on  extra.row_no = c.row_no
    and extra.store = c.store
join    calc cnext
    on  cnext.row_no = case when c.value is null 
                            then extra.next_nr 
                            else c.row_no 
                            end
    and c.store = cnext.store
join    calc cprev
    on  cprev.row_no = case when c.value is null 
                            then extra.prev_nr 
                            else c.row_no 
                            end
    and c.store = cprev.store

答案 1 :(得分:1)

以下是我的想法(storevalue是您示例中的起始表)

with knownvalues as (
select store, shipNtrvl,value
from storevalue where Value is not null
), valueranges as
 (
select 
k.store, 
k.ShipNtrvl as lowrange, 
MIN(s.ShipNtrvl) as highrange,
(select value from storevalue where store = k.store and ShipNtrvl = MIN(s.shipNtrvl))-
(select value from storevalue where store = k.store and ShipNtrvl = k.ShipNtrvl) as     term1,
MIN(s.ShipNtrvl) - k.ShipNtrvl as term2,min(k.Value) as lowval
from knownvalues k
join storevalue s on s.Value is not null and s.store= k.store and s.ShipNtrvl >     k.ShipNtrvl
group by k.store, k.shipntrvl
)
select s.store,s.ShipNtrvl,v.term1/v.term2*(s.ShipNtrvl-v.lowrange)+ v.lowval as value
from storevalue s join valueranges v on v.store = s.store and s.ShipNtrvl between   v.lowrange and v.highrange
where s.Value is null
union 
select * from storevalue where value is not null

只需将select更改为更新即可将值写入表中。