Sql 将表中不再更新的项目的最后一个值结转

Sql 将表中不再更新的项目的最后一个值结转,sql,sql-server,Sql,Sql Server,我在SQL server中有一个表,其中包含多个证券随时间累积的回报 该表如下所示: report_date / security_id / return_usd --------------------------------------- 2016-02-21 / security_a / 2.0 2016-02-22 / security_a / -1.2 2016-02-23 / security_a / -2.7 2016-02-21 / security_b

我在SQL server中有一个表,其中包含多个证券随时间累积的回报

该表如下所示:

report_date / security_id / return_usd
---------------------------------------
2016-02-21  / security_a   /  2.0 
2016-02-22  / security_a   / -1.2
2016-02-23  / security_a   / -2.7
2016-02-21  / security_b   /  5.2  
问题在于,如上文所述,已售出或到期的证券b的累计回报消失

我需要继续为这些证券结转最后的价值回报(美元),如下例所示:

report_date / security_id / return_usd
---------------------------------------
2016-02-21  / security_a   /  2.0 
2016-02-22  / security_a   / -1.2
2016-02-23  / security_a   / -2.7
2016-02-21  / security_b   /  5.2  
2016-02-22  / security_b   /  5.2
2016-02-23  / security_b   /  5.2 

不幸的是,我自己还没有弄清楚,因此如果有人能帮助我,我将不胜感激。

看来您希望对所有证券和日期进行排序,然后结转金额。可以使用交叉联接生成行。然后,在SQL Server 2012+中,可以使用LAG:

注意:这将使用以前的非空值填充任何空值。如果在结束之前没有间隙,那么这应该是您想要的

编辑:

也可以使用外部应用或相关子查询写入:

select d.report_date, s.security_id,
       (select top 1 t.return_usd
        from t
        where t.report_date <= d.report_date and t.security_id = d.security_id and
              t.return_usd is not null
        order by t.report_date desc
       ) as return_usd
from (select distinct report_date from t) d cross join
     (select distinct security_id from t) s left join
     t
     on t.report_date = d.report_date and t.security_id = s.security_id;

这将适用于早期支持的SQL Server版本。

非常感谢。成功了。但是,我认为在第二个解决方案中应该是s.security_id而不是d.security_id,对吗?@SSA。谢谢,我是不是遗漏了什么?看起来你只会把最后一个值向前拉。因此,如果连续两天没有空数据,第二天将结转前一天的空数据。@FISTOFURY。是的,您缺少了忽略null或t.return\u usd不为null的内容,具体取决于您正在查看的查询。
select d.report_date, s.security_id,
       (select top 1 t.return_usd
        from t
        where t.report_date <= d.report_date and t.security_id = d.security_id and
              t.return_usd is not null
        order by t.report_date desc
       ) as return_usd
from (select distinct report_date from t) d cross join
     (select distinct security_id from t) s left join
     t
     on t.report_date = d.report_date and t.security_id = s.security_id;