按月分割行数

时间:2018-02-20 12:49:48

标签: sql tsql

我有一个大数据集(100多万行),我需要根据start_date和end_date之间的月数分成行,以便进行会计。

所以例如这条记录应分成3612行,因为在start_date和end_date之间有3612个月:

enter image description here

我所追求的结果应如下所示:

enter image description here

我知道我可以使用递归CTE来实现这一点,但是对于这么大的数据集需要FOREVER。有没有更有效的方法呢?

3 个答案:

答案 0 :(得分:3)

在此查询中,我使用master.dbo.spt_values作为计数表。但它不适合你,因为它只有2048年的数字。所以你必须创建自己的数字表并在查询中用它更改master.dbo.spt_values

declare @t table (
    id int
    , start_date date
    , end_date date
    , months int
)

insert into @t
values (1, '19990101', '21000101', 1212)

select
    t.id, month_num = v.number + 1
    , total_days = sum(datediff(dd, dateadd(mm, v.number, t.start_date), dateadd(mm, v.number + 1, t.start_date))) over (partition by t.id)
    , t.start_date, t.end_date
from
    @t t
    join master.dbo.spt_values v on t.months > v.number
where
    v.type = 'P'

答案 1 :(得分:0)

declare @numbers TABLE (ID int NOT NULL primary key);  
INSERT INTO  @numbers (ID)
VALUES
   (1)
  ,(2)
  ,(3)
  ,(4)
  ,(5)
  ,(6)
  ,(7)
  ,(8);

declare @range TABLE (cnt int);  
INSERT INTO  @range (cnt)
VALUES (1), (4), (6);

select r.cnt, n.ID
from @range r
join @numbers n 
  on n.ID < = r.cnt 
order by r.cnt, n.ID;

答案 2 :(得分:0)

我不得不在不到一周前做同样的事情!

-----DLL

CREATE TABLE Reporting_Table (
    Credit_Line_NO    Varchar(10),
    noMonths         INT,
    EFFECTIVEDATE    Date,
    EXPIRY_DATE      Date,
    Amount           Money,
    mxDays           INT,
    mxFactor         decimal(5,4),
    Calc             Money)

INSERT INTO Reporting_Table (Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc)
 Values('9938810','3','3/31/2018','6/12/2020','11718.75','90','1','11718.75') 

INSERT INTO Reporting_Table (Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc)
 Values('2235461','1','6/30/2018','6/6/2019','12345','30','1','12345') 

INSERT INTO Reporting_Table (Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc)
 Values('3365434','12','6/30/2018','6/30/2019','298523.36085','365','1.01388888888889','302669.518639583') 

---- VIEW DATA SET . . .
 Select *, (DATEDIFF(MONTH,EFFECTIVEDATE,EXPIRY_DATE)/noMonths)+1 as FREQ
 From Reporting_Table

- 现在你有一个可以摆弄的工作数据集,只需展开所有相关的拖链。

;with cte as
(
  select Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc,
         (DATEDIFF(MONTH,EFFECTIVEDATE,EXPIRY_DATE)/noMonths)+1 as FREQ,
         1 as Rec_Iteration
  from Reporting_Table
  where noMonths > 1
  union all  
  select Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc,
         (DATEDIFF(MONTH,EFFECTIVEDATE,EXPIRY_DATE)/noMonths)+1 as FREQ,
         Rec_Iteration + 1
  from cte 
  where Rec_Iteration < FREQ
)
select Credit_Line_NO, noMonths, EFFECTIVEDATE, EXPIRY_DATE, Amount, mxDays, mxFactor, Calc,
    (DATEDIFF(MONTH,EFFECTIVEDATE,EXPIRY_DATE)/noMonths)+1 as FREQ
from cte
order by Credit_Line_NO,
         Rec_Iteration