sqlserver. Нужно заменить NULL на 0 в результирующем наборе после PIVOT
При добавлении новых строк с новыми месяцами они автоматически прилетают и в запрос с PIVOT. Подскажите плз, как заменить NULL'ы.
create table #gsTestOrdering
(id int identity(1,1), company nvarchar(10), OrderAmount int, OrderDate datetime);
insert into #gsTestOrdering
values
('Газпром',180000,'2017-01-01'),('Роснефть',320000,'2017-01-02'),
('Альфа',80000,'2017-01-01'),('Альфа',45000,'2017-02-05'),
('Роснефть',480,'2017-02-01'),('Газпром',1900,'2017-01-01'),
('Альфа',1200,'2017-01-01'),('Газпром',1550000,'2017-02-01'),
('Роснефть',50060,'2017-01-01'),('Газпром',90000,'2017-01-01'),
('Роснефть',70000,'2017-02-01'),('Газпром',11000,'2017-03-01'),
('Роснефть',9000,'2017-03-01'),('Газпром',150000,'2017-01-01'),
('Альфа',50000,'2017-03-01'),('Роснефть',60000,'2017-03-01'),
('Роснефть',9000,'2017-01-01'),('Газпром',15000,'2017-03-01'),
('Альфа',10000,'2017-02-01'),('Роснефть',60000,'2017-02-01'),
('Газпром',180000,'2017-04-01'),('Роснефть',320000,'2017-05-02')
--,('Альфа',10000,'2017-11-01'),('Роснефть',60000,'2017-08-01') --добавление новых месяцев
--,('Газпром',180000,'2017-12-01'),('Роснефть',320000,'2017-07-02')
;
declare @months table ([mon] varchar(max),
num int identity (1,1))
insert into @months ([mon])
select distinct datename(mm, orderdate) as [mon]
from #gsTestOrdering
declare @val nvarchar(max);
set @val =
(select stuff((select ',' + mon
from @months
for xml path('')
), 1, 1, '')
);
select @val
declare @select nvarchar(max);
set @select = 'select company, ' + @val +
' from
(
select company, sum(orderamount) as sumorder, datename(mm, orderdate) as [mon]
from #gsTestOrdering
group by company, datename(mm, orderdate)
) t
pivot(sum(sumorder)
for [mon]
IN (' + @val + ')
) as d';
exec (@select)
--delete from #gsTestOrdering
--where orderdate in ('2017-11-01', '2017-08-01', '2017-12-01', '2017-07-02') --удаление лишних месяцев
drop table if exists #gsTestOrdering;
Заранее спасибо за помощь.
Ответы (2 шт):
Автор решения: Yitzhak Khabinsky
→ Ссылка
Попробуйте следующее решение. Оно будет работать на SQL Server 2017 и более поздних версиях.
SQL
USE tempdb;
GO
DROP TABLE IF EXISTS #gsTestOrdering;
CREATE table #gsTestOrdering
(id int identity(1,1), company nvarchar(10), OrderAmount int, OrderDate datetime);
insert into #gsTestOrdering
values
(N'Газпром',180000,'2017-01-01'),(N'Роснефть',320000,'2017-01-02'),
(N'Альфа',80000,'2017-01-01'),(N'Альфа',45000,'2017-02-05'),
(N'Роснефть',480,'2017-02-01'),(N'Газпром',1900,'2017-01-01'),
(N'Альфа',1200,'2017-01-01'),(N'Газпром',1550000,'2017-02-01'),
(N'Роснефть',50060,'2017-01-01'),(N'Газпром',90000,'2017-01-01'),
(N'Роснефть',70000,'2017-02-01'),(N'Газпром',11000,'2017-03-01'),
(N'Роснефть',9000,'2017-03-01'),(N'Газпром',150000,'2017-01-01'),
(N'Альфа',50000,'2017-03-01'),(N'Роснефть',60000,'2017-03-01'),
(N'Роснефть',9000,'2017-01-01'),(N'Газпром',15000,'2017-03-01'),
(N'Альфа',10000,'2017-02-01'),(N'Роснефть',60000,'2017-02-01'),
(N'Газпром',180000,'2017-04-01'),(N'Роснефть',320000,'2017-05-02');
declare @months table ([mon] varchar(max), num int identity (1,1));
insert into @months ([mon])
select distinct datename(mm, orderdate) as [mon]
from #gsTestOrdering;
declare @val nvarchar(max);
set @val =
(select stuff((select ',' + mon
from @months
for xml path('')
), 1, 1, '')
);
SELECT @val;
DECLARE @col_list NVARCHAR(MAX);
SET @col_list = (SELECT STRING_AGG('COALESCE(' + value + ',0) AS ' + value, ',')
FROM STRING_SPLIT(@val, ','));
declare @select nvarchar(max);
set @select = 'select company, ' + @col_list +
' from
(
select company, sum(orderamount) as sumorder, datename(mm, orderdate) as [mon]
from #gsTestOrdering
group by company, datename(mm, orderdate)
) t
pivot(sum(sumorder)
for [mon]
IN (' + @val + ')
) as d';
PRINT @select;
EXEC (@select);
Автор решения: Skate_banana
→ Ссылка
create table #gsTestOrdering
(id int identity(1,1), company nvarchar(10), OrderAmount int, OrderDate datetime);
insert into #gsTestOrdering
values
('Газпром',180000,'2017-01-01'),('Роснефть',320000,'2017-01-02'),
('Альфа',80000,'2017-01-01'),('Альфа',45000,'2017-02-05'),
('Роснефть',480,'2017-02-01'),('Газпром',1900,'2017-01-01'),
('Альфа',1200,'2017-01-01'),('Газпром',1550000,'2017-02-01'),
('Роснефть',50060,'2017-01-01'),('Газпром',90000,'2017-01-01'),
('Роснефть',70000,'2017-02-01'),('Газпром',11000,'2017-03-01'),
('Роснефть',9000,'2017-03-01'),('Газпром',150000,'2017-01-01'),
('Альфа',50000,'2017-03-01'),('Роснефть',60000,'2017-03-01'),
('Роснефть',9000,'2017-01-01'),('Газпром',15000,'2017-03-01'),
('Альфа',10000,'2017-02-01'),('Роснефть',60000,'2017-02-01'),
('Газпром',180000,'2017-04-01'),('Роснефть',320000,'2017-05-02')
--,('Альфа',10000,'2017-11-01'),('Роснефть',60000,'2017-08-01') --добавление новых месяцев
--,('Газпром',180000,'2017-12-01'),('Роснефть',320000,'2017-07-02')
;
declare @months table ([mon] varchar(max),
num int identity (1,1))
insert into @months ([mon])
select distinct datename(mm, orderdate) as [mon]
from #gsTestOrdering
declare @val nvarchar(max);
declare @val1 nvarchar(max);
set @val =
(select stuff((select ',' + mon
from @months
for xml path('')
), 1, 1, '')
);
set @val1 =
(select stuff((select ', isnull(' + mon + ', ''0'') as '+ mon
from @months
for xml path('')
), 1, 1, '')
);
select @val;
select @val1;
declare @select nvarchar(max);
set @select = 'select company, ' + @val1 +
' from
(
select company, sum(orderamount) as sumorder, datename(mm, orderdate) as [mon]
from #gsTestOrdering
group by company, datename(mm, orderdate)
) t
pivot(sum(sumorder)
for [mon]
IN (' + @val + ')
) as d';
exec (@select)
----delete from #gsTestOrdering
----where orderdate in ('2017-11-01', '2017-08-01', '2017-12-01', '2017-07-02') --удаление лишних месяцев
drop table if exists #gsTestOrdering;