Вам, скорее всего, придется использовать динамический SQL.
Это ваши данные:
declare @first date = '20150101';
declare @last date = '20150301';
Create Table #items(ItemId int, StartDate date, EndDate date);
Insert into #items(ItemId, StartDate, EndDate) values
(1, '2015-01-01', '2015-06-01')
, (2, '2015-01-01', '2015-02-01')
, (3, '2015-03-01', '2015-08-01')
, (4, '2015-06-01', '2015-10-01');
Вы в первую очередь необходимо, чтобы получить диапазон значений и столбцов:
declare @values varchar(max);
declare @cols varchar(max);
with range(d) as (
Select top(DATEDIFF(month, @first, @last)+1) cast(DATEADD(month, ROW_NUMBER() over(order by (select 0))-1, @first) as varchar(20))
From (
Select 1 From (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x1(n)
Cross Join (values(1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) as x2(n)
) as x(n)
)
Select @values = coalesce(''[email protected]+ ', ', ' ') + '('''+d+''')'
, @cols = coalesce(''[email protected]+ ', ', ' ') + '['+left(DATENAME(month, d), 3)+CAST(year(d) as char(4))+']'
From range
;
В основном это создать строку для каждого date между @first и @last и соединить их скобками и запятыми (@values) или скобками (@cols).
Содержание в @values и @cols выглядеть следующим образом:
@values = ('2015-01-01'), ('2015-02-01'), ('2015-03-01')
@cols = [Jan2015], [Feb2015], [Mar2015]
Вы затем создать SQL скрипт, используя эти 2 переменные:
declare @sql nvarchar(max);
Set @sql = '
Select *
From (
Select i.ItemId, d = left(DATENAME(month, r.d), 3)+CAST(year(r.d) as char(4))
, id = case when r.d >= i.StartDate and r.d <= i.EndDate then i.ItemId end
From (values'[email protected]+') as r(d)
Cross Join (Select ItemId, StartDate, EndDate From #items
Where (@first >= StartDate and @first <= EndDate) or (@last >= StartDate and @last <= EndDate)
) i
) as dates
Pivot (
min(id)
For d in('[email protected]+')
) as piv
';
Это сводный запрос.
Созданный SQL будет выглядеть в этом примере:
Select *
From (
Select i.ItemId, d = left(DATENAME(month, r.d), 3)+CAST(year(r.d) as char(4))
, id = case when r.d >= i.StartDate and r.d <= i.EndDate then i.ItemId end
From (values ('2015-01-01'), ('2015-02-01'), ('2015-03-01')) as r(d)
Cross Join (Select ItemId, StartDate, EndDate From #items
Where (@first >= StartDate and @first <= EndDate) or (@last >= StartDate and @last <= EndDate)
) i
) as dates
Pivot (
min(id)
For d in([Jan2015], [Feb2015], [Mar2015])
) as piv
Вы можете, наконец, выполнить скрипт:
exec sp_executesql @sql, N'@first date, @last date', @first, @last;
Ouput:
ItemId Jan2015 Feb2015 Mar2015
1 1 1 1
2 2 2 NULL
3 NULL NULL 3
Awesome, спасибо! –