SQL Сервер заполняет месячные пробелы в группах - PullRequest
0 голосов
/ 08 мая 2020

У меня есть таблица, например, как показано ниже:

declare @test table(Aid int, Bid int, CheckMonth date, Avalue decimal(18,2))

insert into @test (Aid, Bid, CheckMonth, Avalue)
values (1, 4, '2014-07-05', 123.00)
      ,(1, 4, '2014-08-01', 467.00)
      ,(1, 4, '2014-11-03', 876.00)
      ,(1, 4, '2014-12-01', 876.00)
      ,(2, 6, '2016-01-02', 23.00)
      ,(2, 6, '2016-03-14', 56.00)
      ,(2, 6, '2016-04-17', 98.00)
      ,(2, 6, '2016-07-01', 90.00)

I wi sh, чтобы заполнить пробелы в месяцах (в столбце CheckMonth выше) значениями 0,00 (в столбце Avalue). Данные сгруппированы по столбцам «Помощь» и «Ставка».

Результат должен выглядеть следующим образом:

Aid   Bid    CheckMonth     Avalue
1     4      '2014-07-05'   123.00
1     4      '2014-08-01'   467.00
1     4      '2014-09-01'   0.00    -->inserted
1     4      '2014-10-01'   0.00    -->inserted
1     4      '2014-11-03'   876.00
1     4      '2014-12-01'   876.00
2     6      '2016-01-02'   23.00
2     6      '2016-02-01'   0.00    -->inserted
2     6      '2016-03-14'   56.00
2     6      '2016-04-17'   98.00
2     6      '2016-05-01'   0.00    -->inserted
2     6      '2016-06-01'   0.00    -->inserted
2     6      '2016-07-01'   90.00

Любая помощь приветствуется. Спасибо.

1 Ответ

1 голос
/ 08 мая 2020

Один вариант использует рекурсивный запрос для генерации начала месяца для каждого (aid, bid) кортежа; затем вы можете left join сгенерировать набор результатов с исходной таблицей:

with cte as (
    select 
        aid, 
        bid, 
        datefromparts(year(min(checkMonth)), month(min(checkMonth)), 1) dt, 
        datefromparts(year(max(checkMonth)), month(max(checkMonth)), 1) maxDt 
        from @test
        group by aid, bid
    union all
    select 
        aid, 
        bid, 
        dateadd(month, 1, dt),
        maxDt
    from cte
    where dt < maxDt
)
select c.aid, c.bid, coalesce(t.checkMonth, c.dt) checkMonth, coalesce(t.avalue, 0) avalue 
from cte c
left join @test t 
    on  t.aid = c.aid
    and t.bid = c.bid
    and t.checkMonth >= c.dt
    and t.checkMonth <  dateadd(month, 1, c.dt)
order by c.aid, c.bid, c.dt

Демонстрация на DB Fiddle :

aid | bid | checkMonth | avalue
--: | --: | :--------- | :-----
  1 |   4 | 2014-07-05 | 123.00
  1 |   4 | 2014-08-01 | 467.00
  1 |   4 | 2014-09-01 | 0.00  
  1 |   4 | 2014-10-01 | 0.00  
  1 |   4 | 2014-11-03 | 876.00
  1 |   4 | 2014-12-01 | 876.00
  2 |   6 | 2016-01-02 | 23.00 
  2 |   6 | 2016-02-01 | 0.00  
  2 |   6 | 2016-03-14 | 56.00 
  2 |   6 | 2016-04-17 | 98.00 
  2 |   6 | 2016-05-01 | 0.00  
  2 |   6 | 2016-06-01 | 0.00  
  2 |   6 | 2016-07-01 | 90.00 
...