选择日期范围的每个日期和插入

时间:2014-03-22 21:23:26

标签: sql sql-server-2008

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

示例:

表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。1月和2月只有一个记录所以他们将只是20 / 2 = 10.

我可以想到使用循环的解决方案,但想要完全避免它。 有什么方法可以通过基于集合的解决方案实现这一目标吗?对我来说,使用基于集合的方法批量执行此操作非常重要。

我正在尝试阅读各种文章,看起来像CTE,日历表或理货表可能会有所帮助,但我看到的例子需要设置变量并传递开始日期和结束日期,我认为这对单个记录有用,但不适用于一次做所有记录。请建议。

谢谢!

1 个答案:

答案 0 :(得分:3)

我认为应该这样做(DEMO):

;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

这个想法是使用递归CTE将日期范围分解为每天一条记录。此外,value / (1+datediff(day, startdate, enddate))的逻辑在每个范围内的天数内均匀分配总值。最后,我们按天分组并将与当天相对应的所有值相加以获得输出:

| 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 |

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

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)