Reputation: 577
I have a problem with creating efficient sql query for shop statistics. I have three tables: categories, product_categories and orders_products.
Table categories - contains list of categories and structure looks like(short version):
id
name
Table product_categories - contains connections between products and categories. Structure in short version:
id
product_id
category_id
Table orders_products - contains all products what were sold in shop. Structure below:
id
product_id
price
quantity
What I want to do is display table with category name and value of sold items for current category.
Problem occurs when i have over 2000 categories, more than 20 items in each and many sold items.
I tried:
1) Get all categories in one simple query
2) Foreach them(in php) and use join for products_catogories and orders_products
SELECT orders_products.id,orders_products.product_price_gross,orders_products.product_qty,orders_products.option_price,orders_products.rebate
FROM product_categories
LEFT JOIN orders_products
ON product_categories.product_id = orders_products.product_id
3) Foreach result in php and sum values
4) Display results
5) Effects - hangs db when is more that 50 categories in foreach.
I have no idea how optimize query for that much data. I hope You could help me with that because I'm not so good with joins.
Kind regards Mark
Upvotes: 1
Views: 1577
Reputation: 3514
You might do all thsi stuff in a single step, letting MySQL perform those calculations for you:
SELECT categories.name,
SUM(order_products.price * order_products.quantity)
FROM order_products
LEFT JOIN product_categories ON product_categories.product_id = order_products.product_id
LEFT JOIN categories ON product_categories.category_id = categories.id
GROUP BY categories.name,
categories.id
This will only return the sum for categories, which contain at least a single purchase. See this example sqlfiddle.
I further developed the SQL query (new fiddle) to include quantity per category and add "empty" categories without sales to the reult by turning the JoOIN around:
SELECT categories.name,
Ifnull(Sum(order_products.quantity), 0) AS quantity,
Ifnull(Sum(order_products.price * order_products.quantity), 0) AS `Total Sales`
FROM categories
LEFT JOIN product_categories ON product_categories.category_id = categories.id
LEFT JOIN order_products ON product_categories.product_id = order_products.product_id
GROUP BY categories.name,
categories.id
Upvotes: 1
Reputation: 1009
I am not sure but you can try this,
SELECT orders_products.id,sum(orders_products.product_price_gross),sum(orders_products.product_qty),sum(orders_products.option_price),sum(orders_products.rebate)
FROM product_categories
LEFT JOIN orders_products
ON product_categories.product_id = orders_products.product_id group by product_categories.category_id
Upvotes: 0