Использование динамического TSQL:
if OBJECT_ID('dbo.test') is null
create table dbo.test(App varchar(50), [Date] varchar(50), [Count] int)
truncate table dbo.test
insert into dbo.test values
('Excel', '2018-05-01', 1),
('Excel', '2018-05-02', 1),
('Excel', '2018-05-03', 2),
('Word ', '2018-05-02', 3),
('Word ', '2018-05-07', 5),
('Word ', '2018-05-12', 2),
('Paint', '2018-05-07', 6)
declare @dates nvarchar(max)='' --holds all the dates that will become column names
declare @dates_aliases nvarchar(max)='' --holds the headers without NULL values
declare @sql nvarchar(max)='' --contains the TSQL dinamically generated
select @dates = @dates + ', [' + CONVERT(char(10), [date],126)+ ']' from dbo.test
group by [date]
select @dates_aliases = @dates_aliases + ', isnull(['
+ CONVERT(char(10), [date],126)+ '], 0) as ['
+ CONVERT(char(10), [date],126)+ ']'
from dbo.test group by [date]
set @dates = RIGHT(@dates, len(@dates)-2)
set @dates_aliases = RIGHT(@dates_aliases, len(@dates_aliases)-2)
set @sql = @sql + ' select piv.[App], ' + @dates_aliases
set @sql = @sql + ' from '
set @sql = @sql + ' ( '
set @sql = @sql + ' select [App], [Date], [Count] '
set @sql = @sql + ' from dbo.test '
set @sql = @sql + ' ) src '
set @sql = @sql + ' pivot '
set @sql = @sql + ' ( '
set @sql = @sql + ' max([Count]) '
set @sql = @sql + ' for [Date] in ('+@dates+') '
set @sql = @sql + ' ) piv '
exec(@sql)
Результаты: