TSQL - SQL Server填充值,包含上一个填充日期的值

时间:2017-02-22 21:28:51

标签: sql sql-server tsql

我正试图在我的事实表中找到一件棘手的事情。 我的客户希望使用上一个填充日期的值填充事实表中的每个空值。

Fill Values with previous dates

当我需要整理时,如果维度的上下文相同,那么它应该只更新值。

这是预期的结果:

expected Result

我们正在使用Microsoft Analysis Services,所以也许这也可以通过MDX和LastNonEmpty来完成,但是现在可以获得事实表的工作更新语句。 (通过使用实际事实表交叉连接所有可能的日期组合来生成具有0值的事实表。)

谢谢你们!

1 个答案:

答案 0 :(得分:1)

您可以使用apply

执行此操作
select t.dim1, t.dim2, t.dimdate, t2.value
from t outer apply
     (select top 1 t2.*
      from t t2
      where t2.dim1 = t.dim1 and t2.dim2 = t.dim2 and
            t2.dimdate <= t.dimdate and t2.value <> 0
      order by t2.dimdate desc
     ) t2;

SQL确实提供了使用窗口函数执行所需操作的功能。它是IGNORE NULLS上的LAG()选项。不幸的是,SQL Server没有实现此选项。

您可以使用窗口函数执行此操作,但它有点麻烦:

select t.dim1, t.dim2, t.dimdate,
       max(value) over (partition by dim1, dim2, effectivedimdate) as value
from (select t.*,
             (case when value = 0
                   then max(case when value <> 0 then dimdate end) over (partition by dim1, dim2 order by dimdate)
                   else dimdate
              end) as effective_dimdate
      from t
     ) t;

max()次扫描会获得具有非零值的最新dimdate。然后使用另一个max()扫描将值“扩展”到所有值上。

注意:这假定您要应用的值始终大于零。代码很容易修改以处理这个问题,但额外的case表达式只会使逻辑变得复杂。

其中任何一个都可以轻松转换为更新。第二个特别容易:

with toupdate as (
      select t.*,
             max(value) over (partition by dim1, dim2, effectivedimdate) as new_value
      from (select t.*,
                   (case when value = 0
                         then max(case when value <> 0 then dimdate end) over (partition by dim1, dim2 order by dimdate)
                         else dimdate
                    end) as effective_dimdate
            from t
           ) t
     )
update toupdate
    set value = newvalue
    where value = 0;