我正在零售。 在零售中,我们有供应商提供产品,而我们有客户购买这些产品。有时会发生两个不同的供应商几乎在同一天提供相同产品的情况。因此,我必须使用FIFO算法来确定哪些产品是由第一个供应商出售的,哪些产品是由第二个供应商出售的。并用购物车项目更新表,以指定每个项目的供应商。
我有两个表:
supplies
+----------------------------+-------------+---------+------------+----------+
| supply_date | supplier_id | shop_id | product_id | quantity |
+----------------------------+-------------+---------+------------+----------+
| 2019-03-29 12:00:00.000000 | 5 | 2 | 1 | 110 |
+----------------------------+-------------+---------+------------+----------+
| 2019-03-29 16:00:00.000000 | 7 | 2 | 1 | 50 |
+----------------------------+-------------+---------+------------+----------+
| 2019-04-01 13:00:00.000000 | 6 | 3 | 8 | 30 |
+----------------------------+-------------+---------+------------+----------+
| 2019-04-02 16:00:00.000000 | 8 | 3 | 8 | 90 |
+----------------------------+-------------+---------+------------+----------+
| 2019-04-29 10:00:00.000000 | 1 | 5 | 6 | 25 |
+----------------------------+-------------+---------+------------+----------+
cartitems
+-----------+----------------------------+---------+------------+----------+
| id | date | shop_id | product_id | quantity |
+-----------+----------------------------+---------+------------+----------+
| 515037984 | 2019-04-01 14:25:50.000000 | 2 | 1 | 30 |
+-----------+----------------------------+---------+------------+----------+
| 515043777 | 2019-04-02 13:47:52.000000 | 3 | 8 | 25 |
+-----------+----------------------------+---------+------------+----------+
| 515045460 | 2019-04-02 20:14:30.000000 | 2 | 1 | 80 |
+-----------+----------------------------+---------+------------+----------+
| 515046099 | 2019-04-09 09:55:53.000000 | 2 | 1 | 10 |
+-----------+----------------------------+---------+------------+----------+
| 515046332 | 2019-04-09 11:06:30.000000 | 2 | 1 | 5 |
+-----------+----------------------------+---------+------------+----------+
我尝试了一些方法,它可以工作,但是速度太慢。 UPDATE .. FROM语句的工作非常缓慢。
下面的函数使用FIFO算法,并用cartitems
列更新supplier_id
表。
CREATE OR REPLACE FUNCTION attach_suppliers(shop INTEGER, product INTEGER) RETURNS INTEGER AS $$
DECLARE
-- VARIABLES TO USE
supply_quantity DECIMAL;
var_supplier_id INTEGER;
supply_date TIMESTAMP;
sale_quantity DECIMAL;
cartitem_id INTEGER;
-- SIMPLE COUNTER
updated_count INTEGER = 0;
-- CURSOR FOR MOVING ROW BY ROW IN A QUERY WITH SUPPLIES
supplies_cursor CURSOR FOR
SELECT quantity, supplier_id, supply_date
FROM supplies s
WHERE s.shop_id = $1 AND s.product_id = $2
ORDER BY s.supply_date ASC;
-- CURSOR FOR MOVING ROW BY ROW IN A QUERY WITH CARTITEMS
sales_cursor CURSOR (start_date TIMESTAMP) FOR
SELECT id, quantity
FROM cartitems s
WHERE s.shop_id = $1 AND s.product_id = $2 AND s.date > start_date
ORDER BY s.date ASC;
BEGIN
-- TEMP TABLES TO SAVE REFERENCE BETWEEN CART ITEM AND SUPPLIER
CREATE TEMP table citem_supplier_mapping (
_cartitem_id INTEGER,
_supplier_id INTEGER
);
-- STARTING FROM THE FIRST ROW FROM BOTH TABLES
OPEN supplies_cursor;
FETCH NEXT FROM supplies_cursor INTO supply_quantity, var_supplier_id, supply_date;
OPEN sales_cursor(start_date := supply_date);
FETCH NEXT FROM sales_cursor INTO sale_quantity, cartitem_id;
-- LOOP THROUGH CART ITEMS
LOOP
-- CURRENT ITERATION SHOWS US REFERENCE BETWEEN CART ITEM AND SUPPLIER
supply_quantity := supply_quantity - sale_quantity;
INSERT INTO citem_supplier_mapping (_cartitem_id, _supplier_id) VALUES (cartitem_id, var_supplier_id);
updated_count := updated_count + 1;
-- IF ALL SUPPLIED PRODUCTS WERE SOLD THEN GO TO THE NEXT SUPPLY
IF supply_quantity <= 0 THEN
FETCH NEXT FROM supplies_cursor INTO supply_quantity, var_supplier_id, supply_date;
EXIT WHEN NOT FOUND;
END IF;
-- GO TO THE NEXT CART ITEM
FETCH NEXT FROM sales_cursor INTO sale_quantity, cartitem_id;
EXIT WHEN NOT FOUND;
END LOOP;
-- UPDATE CART ITEMS TABLE WITH `supplier_id` COLUMN TO MAKE REFERENCE
UPDATE cartitems SET supplier_id = _supplier_id FROM citem_supplier_mapping WHERE id = _cartitem_id;
-- CLEAN UP
DROP TABLE citem_supplier_mapping;
CLOSE supplies_cursor;
CLOSE sales_cursor;
RETURN updated_count;
END; $$
LANGUAGE plpgsql;
因此,我希望有这样的表(或只是cartitem_id和Supplier_id之间的映射):
+-----------+----------------------------+---------+------------+----------+-------------+
| id | date | shop_id | product_id | quantity | supplier_id |
+-----------+----------------------------+---------+------------+----------+-------------+
| 515037984 | 2019-04-01 14:25:50.000000 | 2 | 1 | 30 | 5 |
+-----------+----------------------------+---------+------------+----------+-------------+
| 515043777 | 2019-04-02 13:47:52.000000 | 3 | 8 | 25 | 6 |
+-----------+----------------------------+---------+------------+----------+-------------+
| 515045460 | 2019-04-02 20:14:30.000000 | 2 | 1 | 80 | 5 |
+-----------+----------------------------+---------+------------+----------+-------------+
| 515046099 | 2019-04-09 09:55:53.000000 | 2 | 1 | 10 | 7 |
+-----------+----------------------------+---------+------------+----------+-------------+
| 515046332 | 2019-04-09 11:06:30.000000 | 2 | 1 | 5 | 7 |
+-----------+----------------------------+---------+------------+----------+-------------+