Вот один из способов зацикливания данных для получения желаемого результата.
По сути, я построил серию таблиц обработки.Один для фильтрации каждой строки спроса и предложения за один раз, а другой для фактического манипулирования количеством вещей, поставляемых / в строках спроса, это делается для того, чтобы сами данные можно было оставить в покое.Наконец, существует таблица, созданная на лету для генерации самого вывода.
Цикл в основном продолжается до тех пор, пока не останется ничего для фильтрации, и если что-либо еще не выполнено ни из строки предложения, ни из строки спроса, то этотакже вводится в выходную таблицу.На каждом проходе запрашиваются текущие требования и таблицы обработчиков поставщика, чтобы узнать, нужно ли добавлять что-то новое, а затем в конце цикла после того, как сгенерирована выходная строка, все, что находится в 0 или меньше, удаляется из таблиц обработчиков, чтобы гарантировать толькоодна строка спроса или предложения рассматривается одновременно.
РЕДАКТИРОВАТЬ: я добавил цикл для центра.Это означает, что набор данных с несколькими центрами теперь будет работать успешно.
Я также протестировал пример с большим количеством строк.С 48 записями поставки и 80 записями спроса этот запрос создает 128 строк транзакций в секунду, поэтому я подозреваю, что проблемы с производительностью, которые вы замечали, могли быть связаны с цикличностью центра, а не с самой производительностью запроса.Сообщите мне, как вы справляетесь с обновленным запросом, и если есть проблемы с производительностью, мы можем выяснить, почему это так.
Пожалуйста, посмотрите пример запроса и данные, используя данные Center1 и Center 2, предоставленные в вашем комментарии инабор результатов вывода вставлен ниже запроса.
declare @Supply table (
Center nvarchar(20),
[Date] nvarchar(10),
Supply int
);
declare @Demand table (
Center nvarchar(20),
Requirement nvarchar(10),
[Date] nvarchar(10),
Demand int
);
insert @Supply (Center, Date, Supply)
values
('Center1', '1-Sep', 500),
('Center1', '1-Dec', 1000),
('Center2', '1-Oct', 700);
insert @Demand (Center, Requirement, Date, Demand)
values
('Center1', 'Req-1', '1-Aug', 300),
('Center1', 'Req-2', '15-Aug', 250),
('Center1', 'Req-3', '1-Sep', 1100),
('Center2', 'Req-1', '1-Sep', 500),
('Center2', 'Req-2', '1-Oct', 250);
declare @output table
( Center nvarchar(20),
Requirement nvarchar(10),
Req_Dt nvarchar(10),
Supply_Dt nvarchar(10),
Units_supplied int
);
declare @reqfilter table (
Requirement nvarchar(10),
Center nvarchar(20)
);
declare @supfilter table (
Date nvarchar(10),
Center nvarchar(20)
);
declare @req table (
Center nvarchar(20),
Requirement nvarchar(10),
Date nvarchar(10),
Demand int
);
declare @sup table (
Center nvarchar(20),
Date nvarchar(10),
Supply int
);
Declare @Centerfilter table (Center nvarchar(20));
insert @Centerfilter
select distinct Center from @Supply
union
select distinct Center from @Demand;
--select count(*) from @Supply as supply
--select count(*) from @Demand as demand
while exists (select 1 from @Centerfilter)
begin
insert @reqfilter
select requirement, c.Center from @Demand d inner join
(select top 1 Center from @Centerfilter order by Center) c
on d.Center=c.Center;
insert @supfilter
select date, s.Center from @Supply s inner join
(select top 1 Center from @Centerfilter order by Center) c
on s.Center=c.Center;
while exists (select 1 from @reqfilter outer apply @supfilter)
begin
if not exists (select 1 from @req)
begin
insert @req
select top 1 d.Center, d.Requirement, date, demand from
@Demand d inner join @reqfilter r on d.center=r.Center where d.Requirement in (select top 1 Requirement from @reqfilter order by Center, Requirement)
order by Center, parse(date as date);
delete @reqfilter from @reqfilter rq inner join @req r on rq.Requirement=r.Requirement and rq.Center=r.Center;
end
if not exists (select 1 from @sup)
begin
insert @sup
select top 1 s.Center, date, supply from
@Supply s inner join @Centerfilter c on s.Center=c.Center where date in (select top 1 Date from @supfilter order by Center, parse(date as date))
order by center, parse(date as date);
delete @supfilter from @supfilter s inner join @sup su on s.Date=su.date and s.Center=su.Center;
end
insert @output
select coalesce(d.center, s.center), requirement, d.date, s.date, case when supply>Demand then demand else supply end
from @req d inner join @sup s on d.Center=s.Center
update @req set demand=demand-o.Units_supplied
from @req r inner join (select top 1 Center, Requirement, Units_supplied from @output order by Center desc, parse(Req_Dt as date) desc, parse(Supply_Dt as date) desc) o on r.Center=o.Center and r.Requirement=o.Requirement;
update @sup set Supply=supply-units_supplied
from @sup s inner join @req r on s.Center=r.Center
inner join (select top 1 center, requirement, units_supplied from @output order by Center desc, parse(Req_Dt as date) desc, parse(Supply_Dt as date) desc)
o on s.Center=o.Center and r.Requirement=o.Requirement;
delete from @req where Demand<=0;
delete from @sup where Supply<=0;
end
if exists (select 1 from @req)
begin
insert @output
select center, requirement, Date, null, demand from @req;
end
if exists (select 1 from @sup)
begin
insert @output
select center, null, null, date, supply from @sup;
end
delete @Centerfilter where Center in (select top 1 Center from @Centerfilter order by Center);
delete from @reqfilter;
delete from @supfilter;
delete from @req;
delete from @sup;
end
select * from @output;