Sql 根据两个日期之间的月数添加行

Sql 根据两个日期之间的月数添加行,sql,sql-server,Sql,Sql Server,我有一个数据集,其中包含客户可以接受的服务类型的月度预算。服务ID是服务的类型,Begin和End表示服务适合的时间范围,COST表示每月预算金额,NUMBER表示该服务的预算适合的月数 这是一个示例数据集,您会注意到有两个客户机,每个客户机都有两个预算中的服务。一名客户同时接受这两项服务12个月,另一名客户一项服务12个月,另一项服务6个月 CREATE TABLE Services ( ID int, SERVICES_ID int, Begin_DT datetim

我有一个数据集,其中包含客户可以接受的服务类型的月度预算。服务ID是服务的类型,Begin和End表示服务适合的时间范围,COST表示每月预算金额,NUMBER表示该服务的预算适合的月数

这是一个示例数据集,您会注意到有两个客户机,每个客户机都有两个预算中的服务。一名客户同时接受这两项服务12个月,另一名客户一项服务12个月,另一项服务6个月

CREATE TABLE Services (
    ID int,
    SERVICES_ID int,
    Begin_DT datetime, 
    End_DT datetime, 
    COST_PER_MONTH  int, 
    NUMBER_OF_MONTHS int)

('10178',   9,  '7/21/2011',    '7/21/2012' 203.2,  12)
('10178',   10, '7/21/2011',    '7/21/2012' 78.2,   12)
('13862',   12, '12/8/2011',    '6/3/2012', 469.2,  6)
('13862',   10,  '6/3/2011',    '6/3/2012',  78.2,  12)
我需要有一个查询,它在一个月和一个年变量中进行添加,并在Begin_DT和End_DT之间的月份范围内为服务预算的每个月添加行。这就是我想要的:

CREATE TABLE Services_monthly (
    ID int,
    SERVICES_ID int,
    Begin_DT datetime, 
    End_DT datetime, 
    Month int,
    Year int,
    COST_PER_MONTH  int, 
    NUMBER_OF_MONTHS int)

('10178',   9,  '7/21/2011',    '7/21/2012',    7,  2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    8,  2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    9,  2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    10, 2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    11, 2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    12, 2011,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    1,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    2,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    3,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    4,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    5,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    6,  2012,   203.2,  12),
('10178',   9,  '7/21/2011',    '7/21/2012',    7,  2012,   203.2,  12),
('10178',   10, '7/21/2011',    '7/21/2012',    7,  2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    8,  2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    9,  2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    10, 2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    11, 2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    12, 2011,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    1,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    2,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    3,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    4,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    5,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    6,  2012,   78.2,   12),
('10178',   10, '7/21/2011',    '7/21/2012',    7,  2012,   78.2,   12),
('13862',   12, '12/8/2011',    '6/3/2012',     12, 2011,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     1,  2012,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     2,  2012,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     3,  2012,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     4,  2012,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     5,  2012,   469.2,  6),
('13862',   12, '12/8/2011',    '6/3/2012',     6,  2012,   469.2,  6),
('13862',   10, '6/3/2011',     '6/3/2012',     6,  2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     7,  2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     8,  2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     9,  2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     10, 2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     11, 2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',     12, 2011,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',      1, 2012,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',      2, 2012,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',      3, 2012,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',      4, 2012,   78.2,   12),
('13862',   10, '6/3/2011',     '6/3/2012',      5, 2012,   78.2,   12)
请试试这个:

with number_cte (number) as
(select distinct number from master..spt_values where number between 1 and 1000) 

Select  ID, SERVICES_ID,Begin_DT, End_DT,COST_PER_MONTH , NUMBER_OF_MONTHS
from   Services_monthly  s cross join number_cte n
where  n.number <= s.NUMBER_OF_MONTHS
此外,最好的解决方案是创建一个表变量并用数字填充它。

查询:


我想我的小提琴工作起来就像你想要的。

创建一个日历表。包含完整日历的表格,例如从1900年1月1日到2070年12月31日,包括元数据和索引,可以让您快速轻松地确定哪些日期是一周、月、年等的开始,并记录哪些日期是银行假日等。然后加入该表格。@MatBailie谢谢。这将是一个很好的解决方案,但我没有权限在我的作业中创建表。您认为还有其他方法吗?是否可以使用上面的查询创建月份和年份变量?
SELECT  ID, 
        SERVICES_ID,
        Begin_DT, 
        End_DT,
        MONTH(DATEADD(MONTH,n.number, Begin_DT)) AS Month,
        YEAR(DATEADD(MONTH,n.number, Begin_DT)) AS Year,
        COST_PER_MONTH , 
        NUMBER_OF_MONTHS
FROM   Services  s,
(SELECT DISTINCT number 
 FROM master..spt_values 
 WHERE number >= 0 
 AND number < 100)  n
WHERE  n.number <= s.NUMBER_OF_MONTHS
| 13862 |          10 |     June, 03 2011 00:00:00+0000 | June, 03 2012 00:00:00+0000 |     6 | 2012 |           78.2 |               12 |