месяцев между двумя датами в SQL Server с начальной и конечной датой каждой из них в SQL Server с конечной датой может быть ноль - PullRequest
0 голосов
/ 19 сентября 2019

Я хочу получить месяцы между двумя датами с их начальной и конечной датами.Предположим, если я введу начальную дату как «07/06/2019» и конечную дату как «18/09/2019», я хочу перечислить месяцы между их датами начала и окончания соответственно. Пожалуйста, предложите мне, как этого можно достичь.Кроме того, если конечная дата Utc равна нулю, то она должна автоматически делить даты до текущей даты, т.е. 19/09/19

Таблица ввода (BusinessGoal):

BusinessRefId   Period  GoalType                Amount  StartDateUtc      EndDateUtc         Currency
Business C      Year    CommittedTransactionFee 18000   05/07/19 00:00:00 19/09/19 00:00:00  USD

Таблица вывода (BusinessGoal):

BusinessRefId   Period              GoalType                Amount  StartDateUtc         EndDateUtc           Currency
Business C      2019-07 - 2019-08   CommittedTransactionFee 18000   05/07/2019 00:00:00  05/08/2019 00:00:00    USD
Business C      2019-08 - 2019-09   CommittedTransactionFee 18000   05/08/2019 00:00:00  05/09/2019 00:00:00    USD
Business C      2019-09 - 2019-10   CommittedTransactionFee 18000   05/09/2019 00:00:00  05/10/2019 00:00:00    USD

Я уже написал запрос, в котором даты разбиты по годам, т. Е. Если BusinessGoal.Period = 'Year'

declare @BusinessGoal table  
(BusinessRefId varchar(50),   
Period varchar(50), 
GoalType varchar(100),    
Amount money, 
StartDateUtc datetime,   
EndDateUtc datetime, 
Currency varchar(10));

insert into @BusinessGoal values
  ('Business A', 'Year', 'CommittedTransactionFee', 45000, '2019-06-07 00:00:00', NULL, 'USD'),
  ('Business B', 'Year', 'CommittedTransactionFee', 18000, '2017-06-07 00:00:00', NULL, 'USD'),
  ('Business E', 'Year', 'CommittedTransactionFee', 5000 , '2019-04-01 00:00:00', '2019-08-01 00:00:00', 'USD');

select BusinessRefId 
  , cast(ys.y as varchar(4)) + '-' + cast(ys.y + 1 as varchar(4))  Period
  , GoalType, Amount
  , dateadd(year, nmbs.n, tbl.StartDateUtc) StartDateUtc
  , case when ys.NextDate > tbl.EndDateUtc then tbl.EndDateUtc else ys.NextDate end EndDateUtc
  , Currency
from @BusinessGoal tbl
join 
(values (0),(1),(2)
 ) nmbs(n)
on dateadd(year, nmbs.n, tbl.StartDateUtc) <= getdate() 
  and (EndDateUtc is null or EndDateUtc >= datefromparts(Year(tbl.StartDateUtc) + nmbs.n + 1, 1, 1))
cross apply (select Year(tbl.StartDateUtc) + nmbs.n y, dateadd(year, nmbs.n + 1,tbl.StartDateUtc) NextDate) ys

Я должен интегрировать разбиениедаты по месяцам и годам путем реализации проверки столбца Период таблицы BusinessGoal, т. е. если BusinessGoal.Period = 'Year' и if BusinessGoal.Period = 'Month'.

1 Ответ

2 голосов
/ 19 сентября 2019

Вот как написать рекурсивный CTE, предложенный Кайусом Джардом в комментариях:

-- Create a Test Table
select '2019-07-05' as StartDateUtc, '2019-09-19' as EndDateUtc
into #test;

-- Recursive CTE that returns the months between StartDateUtc and EndDateUtc
with months as (
  -- initial values of the recursive CTE
  select datefromparts(year(StartDateUtc), month(StartDateUtc), 1) as StartPeriod,
         dateadd(month, 1, datefromparts(year(StartDateUtc), month(StartDateUtc), 1)) as EndPeriod,
         t.StartDateUtc, t.EndDateUtc
  from #test t
  union all
  -- we recursively add 1 month until we reach EndDateUtc
  select dateadd(month, 1, StartPeriod) as StartPeriod,
         dateadd(month, 1, EndPeriod) as EndPeriod,
         months.StartDateUtc, months.EndDateUtc
  from months 
  where dateadd(month, 1, StartPeriod) <= coalesce(EndDateUtc, StartDateUtc)  -- If EndDateUtc is null then we use StartDateUtc, so only the first month is returned
)
select * from months;

-- Drop Test Table
drop table #test;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...