views:

1819

answers:

3

I have two tables, one stores the products and quantity we have bought, the other stores the sells. The current stock is therefore the sum of all the quantity columns in the bought table minus the number of rows in the sells table. How can this be expressed in MySQL. Remember that there are many different products.

EDIT: To make it harder, I have another requirement. I have the bought table, the sold table, but I also have the products table. I want a list of all the products, and I want to know the quantity available of each product. The problem with the current answers is that they only return the products that we have sold or bought already. I want all the products.

+6  A: 

Try this


SELECT inv_t.product_id, inventory_total-nvl(sales_total,0)
FROM 
  (SELECT product_id, sum(quantity) as inventory_total
   FROM inventory
   GROUP BY product_id) inv_t LEFT OUTER JOIN
  (SELECT product_id, count(*) AS sales_total 
   FROM sales 
   GROUP BY product_id) sale_t
  ON (inv_t.product_id = sale_t.product_id)

This is a better solution than a few of the other ones posted, which do not account for the fact that some products may not have any corresponding rows in the sales table. You want to make sure that such products also show up in the results.

NVL is an Oracle-specific function that returns the value of the first argument, unless it's null, in which case it returns the value of the second argument. There are equivalent functions in all commercial DBMSes -- you can use CASE in MySQL to the same effect.

SquareCog
I think you meant inv_t.product on the first line.
Marius
Also, it does not show a product which hasn't been sold yet.
Marius
Thanks for the catch, fixed. It does show a product which hasn't been sold, that's why it's an outer join. I added an nvl() call, to make clear that this is what should be happening.
SquareCog
IFNULL() does the same thing in MySQL
Marius
A: 
SELECT product AS prd, 
SUM(quantity) - 
  IFNULL((SELECT COUNT(*)
   FROM sells
   WHERE product = prd 
   GROUP BY product), 0)
AS stock 
FROM bought
GROUP BY product;

This one also works when quantity sold is 0.

Marius
A: 

I suggest making the "inventory" and "sales" tables into views, so that they are re-usable and the final query becomes very simple. Obviously the field and table names will need to change to match your schema.

--First view: list products and the purchased qty
create or replace view product_purchases as
select
  product_id
 ,sum(purchased_qty) as purchased_qty
from
  purchases
group by
  product_id;

--Second view: list of products and the amount sold    
create or replace view product_sales as
select
  product_id
 ,count(*) as sales_qty
from
  sales
group by
  product_id;

--after creating those two views, run this query:
select
  pp.product_id
 ,pp.purchased_qty - ps.sales_qty as on_hand_qty
from
  product_purchases pp
 ,product_sales ps
where ps.product_id = pp.product_id;
JosephStyons