Сумма SQL по разделу - PullRequest
0 голосов
/ 29 июня 2018

У меня есть 6000 штук на складе, а запас делится на 2 партии, содержащие 4000 штук и 2000 штук.

На основании заказов клиентов я пытаюсь предсказать, какая партия товара будет выполнять каждый заказ.

Например:

SELECT product, order_qty, price, date_required FROM orders Where product = 'X'

Это производит эту таблицу:

product | order_qty | price |  date_required
------------------------------------------------------
 X      | 300       | 1.01  |   01/07/2018
 X      | 500       | 1.00  |   03/07/2018
 X      | 700       | 1.05  |   02/07/2018
 X      | 1000      | 1.00  |   01/08/2018
 X      | 2000      | 1.00  |   20/07/2018
 X      | 600       | 1.06  |   10/07/2018
 X      | 500       | 1.10  |   11/07/2018
 X      | 400       | 1.00  |   10/08/2018

Тогда у меня есть другой запрос, например:

SELECT batch, product, qty, date_received FROM batches where product = 'X'

Это приведет к созданию таблицы, подобной этой:

 batch  |product| qty   |  date_received
-------------------------------------------
 ABC123 | X     | 2000  |   01/04/2018
 987ZYX | X     | 4000  |   01/01/2018

Таким образом, используя эти две таблицы, я хотел бы предсказать, из какой партии будет поступать заказ на покупку. Запас использует систему FIFO, поэтому на основе таблицы он должен будет выполнить заказы сначала с использованием кода партии 987ZYX. Я ищу запрос, который производит это в виде таблицы:

product | order_qty | price |  date_required|   batch
------------------------------------------------------------------
 X      | 300       | 1.01  |   01/07/2018  |   987ZYX
 X      | 500       | 1.00  |   03/07/2018  |   987ZYX  
 X      | 700       | 1.05  |   02/07/2018  |   987ZYX
 X      | 1000      | 1.00  |   01/08/2018  |   ABC123
 X      | 2000      | 1.00  |   20/07/2018  |   987ZYX & ABC123
 X      | 600       | 1.06  |   10/07/2018  |   987ZYX
 X      | 500       | 1.10  |   11/07/2018  |   987ZYX
 X      | 400       | 1.00  |   10/08/2018  |   ABC123

Я выбрал вышеуказанные партии на основе требуемой даты, например, первый требуемый заказ - 1/7/18, чтобы удалить 300 штук из партии 987ZYX, затем я продолжал в этом методе, пока мне не пришлось выполнить заказ из следующей партии

Я понимаю, что мог бы использовать метод SUM over, но как я могу использовать его, чтобы убедиться, что он не использует больше запаса, чем доступно в пакете, как вы можете видеть выше, я хотел бы отобразить две партии, если возможно, если его нужно будет выполнить из двух.

1 Ответ

0 голосов
/ 29 июня 2018

Во-первых, я ненавижу даты (частично потому, что мой день рождения 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...