Комплектация заказов на складе - PullRequest
0 голосов
/ 09 сентября 2018

При внедрении системы управления складом для интернет-магазина я пытаюсь создать список комплектации для работников склада, которые будут ходить по складу, собирая товары по заказам с разных полок.

Один тип продукта может быть на разных полках, и на каждой полке может быть много одного и того же типа продукта.

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

Чтобы еще больше усложнить задачу, иногдатовара также будет на складе.

Моя модель данных выглядит следующим образом (упрощенно):

CREATE TABLE order_product (
    id SERIAL PRIMARY KEY,
    product_id integer,
    order_id text
);

INSERT INTO "public"."order_product"("id","product_id","order_id")
VALUES
(1,1,'order1'),
(2,1,'order1'),
(3,1,'order1'),
(4,2,'order1'),
(5,2,'order2'),
(6,2,'order2');

CREATE TABLE warehouse_placement (
    id SERIAL PRIMARY KEY,
    product_id integer,
    shelf text,
    quantity integer
);

INSERT INTO "public"."warehouse_placement"("id","product_id","shelf","quantity")
VALUES
(1,1,E'A',2),
(2,2,E'B',2),
(3,1,E'C',2);

Возможно ли в postgres создать список выбора инструкций, напримерследующее:

order_id product_id shelf quantity_left_on_shelf
order1   1          A     1
order1   1          A     0
order1   2          B     1
order1   1          C     1
order2   2          B     0
order2   2         NONE   null     

В настоящее время я делаю это в коде приложения, но это выглядит довольно неуклюже, и почему-то мне кажется, что должен быть способ сделать это непосредственно в SQL.

Спасибо залюбая помощь!

1 Ответ

0 голосов
/ 10 сентября 2018

Вот и мы:

WITH product_on_shelf AS (
    SELECT warehouse_placement.*, 
           generate_series(1, quantity) AS order_on_shelf,
           quantity - generate_series(1, quantity) AS quantity_left_on_shelf
    FROM warehouse_placement
)
, product_on_shelf_with_product_order AS (
    SELECT *,
           ROW_NUMBER() OVER (
               PARTITION BY product_id 
               ORDER BY quantity, shelf, order_on_shelf
           ) AS order_among_product
    FROM product_on_shelf
)
, order_product_with_order_among_product AS (
    SELECT *,
           ROW_NUMBER() OVER (
               PARTITION BY product_id 
               ORDER BY id
           ) AS order_among_product
    FROM order_product
)
SELECT order_product_with_order_among_product.id,
       order_product_with_order_among_product.order_id,
       order_product_with_order_among_product.product_id,
       product_on_shelf_with_product_order.shelf,
       product_on_shelf_with_product_order.quantity_left_on_shelf
FROM order_product_with_order_among_product
LEFT JOIN product_on_shelf_with_product_order
    ON order_product_with_order_among_product.product_id = product_on_shelf_with_product_order.product_id
    AND order_product_with_order_among_product.order_among_product = product_on_shelf_with_product_order.order_among_product
ORDER BY order_product_with_order_among_product.id
;

Вот идея :

  1. Мы создаем временную таблицу product_on_shelf, которая аналогична warehouse_placement, за исключением того, что строки дублируются n раз, при этом n является количеством товара на полке.
  2. Мы присваиваем номер order_among_product каждой строке в product_on_shelf, чтобы каждый объект на полке знал свой порядок среди одних и тех же продуктов.
  3. Мы присваиваем симметричный номер order_among_product каждой строке в order_product.
  4. Для каждой строки в order_product мы пытаемся найти продукт на полке с таким же order_among_product. Если мы не можем их найти, значит, мы исчерпали продукты на любой полке.

Примечание № 1 : Сбор продуктов с полок является одновременным действием. Вы должны убедиться, либо со стороны приложения, либо со стороны БД с помощью интеллектуальных замков, что любой продукт на полке можно отнести к одному заказу. Обработка каждой строки product_order на стороне приложения может быть лучшим вариантом для решения проблемы совпадения.

Примечание № 2 : Я написал этот запрос, используя CTE для ясности. Чтобы повысить производительность, рассмотрите возможность использования подзапросов. Обязательно запустите EXPLAIN ANALYZE

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