Во-первых, я ненавижу даты (частично потому, что мой день рождения 29 февраля, частично потому, что мой ключ 'd' не работает должным образом), поэтому я создал индекс для каждого заказа и каждой партии, и я предполагаю, что заказы должны быть обработаны в порядке возрастания индекса от минимально возможного индекса партии. Я также не проверяю, есть ли товары на складе на момент заказа, а также многое другое.
Как предложил @GordonLinoff, мы будем использовать кумулятивные суммы. Я создаю новые таблицы с накопленным количеством для таблиц #orders и #batch (мы просто суммируем все количество от заказов / партий с id до текущего). И затем мы рекурсивно вычисляем партию, которая ... ну, мы как-то находим нужную партию. Я думаю, нам не нужна рекурсия, но я только что узнал, как использовать ее в SQL, поэтому я горжусь тем, что использую ее в ненужных местах. О, и я также забыл проверить, совпадает ли продукт из партии и заказов ...
drop table if exists #orders, #batch, #orders_cumulative, #batch_cumulative
create table #orders (id int, product varchar(10), order_qty int, price float, date_required date)
insert into #orders VALUES
(1, 'x', 300, 1.01, '20180107'),
(2, 'y', 500, 1, '20180307'),
(3, 'x', 700, 1.05, '20180207'),
(4, 'x', 1000, 1, '20180108'),
(5, 'x', 2000, 1, '20180402'),
(6, 'x', 600, 1.06, '20180302'),
(7, 'y', 100, 1, '20180203'),
(8, 'x', 100, 1, '20180402')
create table #batch (id int, batch varchar(10), product varchar(10), qty int)
insert into #batch VALUES
(1, 'abc', 'x', 1000),
(2, 'zxc', 'x', 1000),
(3, 'sd', 'x', 2000),
(4, 'eiso', 'y', 10000)
SELECT o.*
,(select sum(order_qty) from #orders where id <= o.id and product = o.product) cumulative_qty
INTO #orders_cumulative
from #orders o
select b.*
,isnull((select sum(qty) from #batch where id < b.id and product = b.product), 0) cumulative_ex_qty
,(select sum(qty) from #batch where id <= b.id and product = b.product) cumulative_qty
into #batch_cumulative
FROM #batch b
select top 10 * from #orders_cumulative
select top 10 * from #batch_cumulative
select oc.*
,case when bc.cumulative_ex_qty > oc.cumulative_qty - oc.order_qty then convert(varchar(10), isnull(b1.batch, '') + ', ' + b2.batch) else b2.batch end batch
from #orders_cumulative oc
join #batch_cumulative bc on oc.cumulative_qty between bc.cumulative_ex_qty and bc.cumulative_qty and oc.product = bc.product
join #batch b2 on b2.id = bc.id
left JOIN #batch b1 on b1.id = bc.id - 1
РЕДАКТИРОВАТЬ: я исправил основные проблемы (отдельные расчеты для каждого продукта, устранена глупая рекурсия), за исключением даты и времени, которые были изменены на id.