在T-SQL中添加缺少的月份

时间:2017-08-28 09:14:59

标签: sql tsql datetime

我有类似这样的数据:

LoanId  PaymentDate PaymentMonth PaymentAmount
  L1     12-01-2008    01             100
  L2     15-02-2008    02             300
  L3     01-04-2008    04             500
  L3     01-10-2008    10             500  

我想为每个loanId添加缺少的PaymentMon,如下所示:

    LoanId  PaymentYear PaymentMonth PaymentAmount
  L1           2008        01             100
  L1           2008        02              0
  L1           2008        03              0
  ..            ..         ..             ..
  L1           2008        12              0
  L2           2008        01              0
  L2           2008        02             300
  L2           2008        03              0
  ..            ..         ..             ..
  L3           2008        01              0
  L3           2008        02              0
  L3           2008        03              0
  L3           2008        04             500
  ..            ..         ..             ..
  L3           2008        10             500
  ..            ..         ..              ..
  L3           2008        12              0

手动完成,但现在从2008年到2007年获得了超过10万的贷款

4 个答案:

答案 0 :(得分:2)

尝试这样做:

use db_test;
go

create table dbo.test1 
(
    loanId          varchar(2),
    paymentDate     date,
    paymentMonth    varchar(2),
    paymentAmount   float
);

set dateformat dmy;

insert into dbo.test1 
values 
    ('L1', '12-01-2008', '01', 100),
    ('L2', '15-02-2008', '02', 300),
    ('L3', '01-04-2008', '04', 500),
    ('L3', '01-10-2008', '10', 500);  

set dateformat ymd;

with cte as (
    select cast('2008-01-31' as date) as month_dt, 1 as month_nm, format(1, 'd2') as paymentMonth
    union all
    select eomonth(dateadd(month, 1, month_dt)), month_nm + 1, format(month(month_dt) % 12 + 1, 'd2') 
    from cte
    where month_dt < '2012-12-31'
), cte2 as (
    select 
        t.loanId, 
        x.month_dt,
        x.paymentMonth
    from (
        select distinct loanId from dbo.test1
    ) t
    join cte x 
        on 1 = 1
)
select
    a.loanId, year(a.month_dt) as paymentYear, a.paymentMonth, coalesce(b.sm, 0) as paymentAmount
from 
    cte2 a
    left join (
        select loanId, eomonth(paymentDate) as paymentDate, paymentMonth, sum(paymentAmount) as sm
        from dbo.test1
        group by loanId, eomonth(paymentDate), paymentMonth
    ) b
        on a.month_dt = b.paymentDate
        and a.loanId = b.loanId
order by 
    paymentYear asc,
    loanId asc,
    paymentMonth;

答案 1 :(得分:2)

你可以试试:

1。)获取你的MIN&amp; MAX PaymentDate(因为我认为这是你的范围)
2.)创建此范围内的所有月份 - 在我的示例中使用公用表表达式。) 3.)最后选择您的数据并加入这些月份日期并将结果分组

DECLARE @StartDate  DATETIME,
        @EndDate    DATETIME;

SET @StartDate = SELECT MIN(PaymentDate) 
                   FROM yourtable

SET @EndDate   = SELECT MAX(PaymentDate) 
                   FROM yourtable

;WITH CTE AS (
    SELECT DATEADD(MONTH, x.number, @StartDate) as Months
      FROM master.dbo.spt_values x
     WHERE x.type = 'P'        
       AND x.number <= DATEDIFF(MONTH, @StartDate, @EndDate)
)
  SELECT yourtable.LoanID
        ,yourtable.PaymentYear
        ,yourtable.PaymentMonth
        ,SUM(ISNULL(PaymentAmount,0)) as PaymentAmount
    FROM CTE
    INNER JOIN yourtable
      ON yourtable.PaymentYear = CONVERT(VARCHAR(4),DATEPART(YEAR, Months)) 
     AND yourtable.PaymentMonth = RIGHT('0' + CONVERT(VARCHAR(2),DATEPART(MONTH, Months)),2)
GROUP BY yourtable.LoanID
        ,yourtable.PaymentYear
        ,yourtable.PaymentMonth   

答案 2 :(得分:1)

这是一种方法,非常简单。代码中包含必要的注释。

declare @LoanData table (
ID char(2),
PaymentDate date,
PaymentAmount int
)
insert into @LoanData values
('L1', '01-12-2008',100),
('L2', '02-15-2008',300),
('L3', '04-01-2008',500),
('L3', '10-01-2008',500)
declare @TableID table(id char(2))
--list of IDs
insert into @TableID select distinct ID from @LoanData

declare @PaymentMonth table(
LoanID char(2),
PaymentYear int,
PaymentMonth int,
PaymentAmount int
)
declare @month int, @year int, @i int, @id char(2)
select @i = count(*) from @TableID

--first get the table which has recotrd for every month for every id (default value in PaymentAmount is 0)
while @i > 0
begin
    select top 1 @id = id from @TableID

    set @year=2008
    while @year <= 2012
    begin
        set @month=1
        while @month <= 12
        begin
            insert into @PaymentMonth values (@id, @year, @month, 0)
            set @month = @month + 1
        end

        set @year = @year + 1
    end
    delete from @TableID where id = @id
    set @i = @i - 1
end
--update table based on your initial data
update @PaymentMonth
set PaymentAmount = A.PaymentAmount from @LoanData as A
where LoanID = A.ID and PaymentYear = datepart(YEAR, A.PaymentDate) and PaymentMonth = datepart(MONTH, A.PaymentDate)

select * from @PaymentMonth

答案 3 :(得分:0)

create table temp_loantable (
loanid bigint,
paymentdate date,
paymentmonth varchar(2),
paymentamount numeric(10,2))

拥有日期范围(年和月),然后执行左外连接应获得所需的输出。

select * from 
(select years.n yearval , months.n monthval
from (values(2008), (2009), (2010), (2011), (2012)) years(n),
(values(1),(2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) months(n)) a
left outer join temp_loantable l 
on year(paymentdate) = a.yearval 
   and month(paymentdate) = a.monthval