Sql 为日期范围选择每个日期并插入

Sql 为日期范围选择每个日期并插入,sql,sql-server-2008,Sql,Sql Server 2008,使用SQL Server 2008 我有一个表a,它有开始日期、结束日期和值。对于表A中开始日期和结束日期内的每个日期,我需要在表B中插入(或更新,如果已经存在)该日期,以便该表中的值为A/DateDiff中的值(天,A的开始日期,A的结束日期) 例如: 表A ID StartDate EndDate Value 1 01 Jan 2014 03 Jan 2014 33 2 01 Feb 2014 0

使用SQL Server 2008
我有一个表a,它有开始日期、结束日期和值。对于表A中开始日期和结束日期内的每个日期,我需要在表B中插入(或更新,如果已经存在)该日期,以便该表中的值为A/DateDiff中的值(天,A的开始日期,A的结束日期)

例如:

表A

ID    StartDate        EndDate           Value    
1     01 Jan 2014      03 Jan 2014       33
2     01 Feb 2014      02 Feb 2014       20
3     02 Jan 2014      03 Jan 2014       10
表B

ID    Date            Value
1     01 Jan 2014     11
2     02 Jan 2014     16
3     03 Jan 2014     16
4     01 Feb 2014     10
5     02 Feb 2014     10

计算值的方式是-对于ID 1,有3天,即每天11个单位。所以1月1日,2日,3日都有11个单位。然后,由于有额外的单位,其日期范围为1月2日至1月3日,相当于每天5个单位,1月2日和3日将为(11+5)16。2月1日和2日只有一个记录,因此它们将只是20/2=10

我可以想到一个使用循环的解决方案,但我想完全避免它。 我有没有办法通过基于集合的解决方案来实现这一点?对我来说,使用基于集合的方法批量完成这项工作非常重要

我试图通读各种文章,似乎CTE、日历表或理货表可能会有所帮助,但我看到的示例要求设置变量并传递开始日期和结束日期,我认为这对单个记录有效,但对一次处理所有记录无效。请建议

谢谢

我认为应该这样做():

从这里,您可以按日期加入结果表(表B),并根据需要更新/插入值。该逻辑可能看起来像这样(当然,在投入生产运行之前先测试它!):


你的价值观毫无意义。它们不应该是11、16、33、10、20吗?计算值的方式是——对于ID 1,有3天,这意味着每天11个单位。所以1月1日,2日,3日都有11个单位。然后,由于有额外的装置,其日期范围为1月2日至1月3日,总计每天5台,因此1月2日和3日将为16台。2月1日和2日只有一个记录,因此它们将只是20/2=10。我想说的是,你应该删除这个问题,从描述开始。你的意思是在描述中解释计算?有一些巧妙的技巧可以解决这个问题(比如使用两个递归cte,一个分解为100天或更少的日期范围,然后第二个完全分解)。一个范围的最大尺寸是否有硬限制?您可以将最大递归深度设置为比默认值100更高的值。是的,我想我可以使用默认值。对不起,我不知道,只是在评论后才意识到,所以删除了那个评论。但是谢谢你的回复。你能告诉我完全取消限额有什么害处吗?
;with cte as (
  select
     id
    ,startdate
    ,enddate
    ,value / (1+datediff(day, startdate, enddate)) as value
    ,startdate as date
  from units
  union all
  select id, startdate, enddate, value, date+1 as date
  from cte
  where date < enddate
)
select
   row_number() over (order by date) as ID
  ,date
  ,sum(value) as value
from cte
group by date
| ID |                            DATE | VALUE |
|----|---------------------------------|-------|
|  1 |  January, 01 2014 00:00:00+0000 |    11 |
|  2 |  January, 02 2014 00:00:00+0000 |    16 |
|  3 |  January, 03 2014 00:00:00+0000 |    16 |
|  4 | February, 01 2014 00:00:00+0000 |    10 |
|  5 | February, 02 2014 00:00:00+0000 |    10 |
update B set B.VALUE = R.VALUE from TableB B join Result R on B.DATE = R.DATE
insert TableB (DATE, VALUE)
  select DATE, VALUE from Result R where R.DATE not in (select DATE from TableB)