Bla...
Bla...

Reputation: 7288

Stock calculation during sales

I have a StockCard table with below schema:

create table StockCard(
    id int(9) zerofill primary key auto_increment,
    ref_page smallint(3) not null,
    ref_number int(9) not null,
    sur_key int unsigned null,
    description varchar(255),
    warehouse_product_id int(9) zerofill not null,
    sc_date datetime not null,
    qty int not null,
    price double(15,2) not null,
    reserved_qty int not null,
    left_qty int not null,
    status boolean not null, /* true = buy, false = sell*/
    CONSTRAINT FOREIGN KEY (warehouse_product_id) REFERENCES Warehouse_Product(id),
    CONSTRAINT FOREIGN KEY (ref_page) REFERENCES Page(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

For now, when I want to sell a product I use LIMIT to know whether I got enough left_qty/stock for selling that product. Below is my query, which runs in a for loop as long as avail_stock still below ordered_qty:

SELECT SUM(StockCard.left_qty) AS avail_qty FROM StockCard 
LEFT JOIN Warehouse_Product ON Warehouse_Product.id = StockCard.warehouse_product_id
WHERE Warehouse_Product.product_id = {product_id}
AND StockCard.status = 1 AND left_qty > 0
ORDER BY sc_date ASC, id ASC
LIMIT {row_limit} 
//this row_limit will increase in every loop as long as the SUM smaller than the ordered qty

My question here, is it true that by using my approach above it will improve my query performance or should I just delete the LIMIT? Feel free to give other approach..

Here is the simplified version of my issue: http://sqlfiddle.com/#!9/36ef5

Upvotes: 1

Views: 119

Answers (1)

Kokizzu
Kokizzu

Reputation: 26818

Don't use LIMIT, it would be a lot of queries generated. See the fiddle here, first you need to calculate the sum of previous (see x2 or minqty) and sum of previous and current (see x1 or maxqty) then use them to filter what you need.

SELECT x3.*
FROM
    ( SELECT sc1.*, IFNULL(SUM(sc2.left_qty),0) maxqty
    FROM StockCard sc1
      LEFT JOIN StockCard sc2 ON sc2.id <= sc1.id
    WHERE sc1.status = 1 AND sc2.status = 1 AND sc1.warehouse_product_id = 1 AND sc2.warehouse_product_id = 1
    GROUP BY sc1.id
    ORDER BY sc2.sc_date ASC, sc2.id ASC ) x1
  LEFT JOIN
    ( SELECT sc1.*, IFNULL(SUM(sc2.left_qty),0)+1 minqty
    FROM StockCard sc1
      LEFT JOIN StockCard sc2 ON sc2.id < sc1.id
    WHERE sc1.status = 1 AND sc2.status = 1 AND sc1.warehouse_product_id = 1 AND sc2.warehouse_product_id = 1
    GROUP BY sc1.id
    ORDER BY sc2.sc_date ASC, sc2.id ASC ) x2
  ON x1.id = x2.id
  LEFT JOIN StockCard x3 ON x3.id <= x1.id 
    AND x3.warehouse_product_id = sc1.warehouse_product_id
WHERE IFNULL(x2.minqty,0) <= 15 -- > change these
  AND x1.maxqty >= 15 --> change these

For example when the table contains: 15, 2 and 3, minqty and maxqty would be:

qty min max
15    1  15
 2   16  17
 3   18  21

Upvotes: 1

Related Questions