Я думаю, я понял это. Это, вероятно, не красиво, но немного времени, и, прочитав идею Бет, у меня возникла искра.
Я придумал:
create procedure sp_MIS_mySP
@fromDate datetime=null,
@toDate datetime=null,
@debug int=0
as
-- get overall date range
declare @firstDate datetime
declare @lastDate datetime
select top 1 @firstDate=Start from MIS_Policies where (@fromDate is null or Start>=@fromDate) order by Start
select top 1 @lastDate=End from MIS_Policies where (@toDate is null or End<=@toDate) order by End desc
if @debug=1
begin
print 'Parameters:'
if (@fromDate is null) print ' @fromDate=NULL' else print ' @fromDate='''+rtrim(convert(varchar,@fromDate))+''''
if (@toDate is null) print ' @toDate=NULL' else print ' @toDate='''+rtrim(convert(varchar,@toDate))+''''
print 'Evaluated:'
print ' @firstDate='''+rtrim(convert(varchar,@firstDate))+''''
print ' @lastDate='''+rtrim(convert(varchar,@lastDate))+''''
end
-- step through date range by month
-- inserting count of active contracts at that point
declare @dateTImePtr datetime
set @dateTImePtr=dateadd(d,-(datepart(d,@firstDate)-1),@firstDate)
declare @startOfMonthPtr datetime
declare @endOfMonthPtr datetime
create table #yearMonthActiveBreakdown (
[year] int,
[month] int,
[count] int)
while @dateTImePtr<=@lastDate
begin
set @startOfMonthPtr=@dateTImePtr
set @endOfMonthPtr=DATEADD(m,1,@startOfMonthPtr)
set @endOfMonthPtr=DATEADD(d,-1,@endOfMonthPtr)
if @debug=1
begin
print '@dateTimePtr='''+rtrim(convert(varchar,@dateTimePtr))+''' (@startOfMonthPtr='''+rtrim(convert(varchar,@startofMonthPtr))+''', @endOfMonthPtr='''+rtrim(convert(varchar,@endOfMonthPtr))+''')'
end
-- insert row for year/month aggregating by count of items
insert into #yearMonthActiveBreakdown ([year],[month],[count])
select year(@dateTImePtr),
MONTH(@dateTImePtr),
COUNT(ContractNumber)
from MIS_Policies
where
Start<=@endOfMonthPtr and End>=@startOfMonthPtr and Status in (0,3,4,5)
set @dateTImePtr=DATEADD(m,1,@dateTimePtr)
end
if @debug = 1
begin
-- pre-pivot
select * from #yearMonthActiveBreakdown
end
select [YEAR],[1] as [Exposure_1],[2] as [Exposure_2],[3] as [Exposure_3],[4] as [Exposure_4],[5] as [Exposure_5],[6] as [Exposure_6],[7] as [Exposure_7],[8] as [Exposure_8],[9] as [Exposure_9],[10] as [Exposure_10],[11] as [Exposure_11],[12] as [Exposure_12]
from (
select [Year],[Month],[Count]
from #yearMonthActiveBreakdown p
) as s
pivot (sum([Count])
for [Month] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) as pivoted
drop table #yearMonthActiveBreakdown
Итак, я беру общий диапазон дат и создаю цикл, повторяя этот цикл в месяц. Кажется, он выводит то, что мне нужно, но уже поздно, и я не могу проверить, пока не вернусь в офис. Я думал, что этого итеративного подхода мне удастся избежать, но, думаю, нет.
Обновлены
Обновлен чуть более производительный код качества, включая соображения, выделенные Андреем.