Sum with inner join in PHP - php

I'm working with PHP and MySQL, and I need to SUM the total amount of products joining 3 tables:
order_products: (There are multiple order products with the same name but different amounts in the table)
order_id (int)
product_name (varchar)
product_amount (int)
orders:
order_id (int)
order_date (varchar)
order_status (varchar)
supplier:
product_name (varchar)
product_amount (int)
So, I want to show how many products I sold and status is shipped and how many I ordered from the supplier in one single row. Any of two examples below will help me to achieve my goal.
Like:
Product Name (sum order_products) (sum supplier) Order status
first product 300 2500 Shipped_Only
second product 50 400 Shipped_Only
third product 10 600 Shipped_Only
Product Name (sum order_products) (sum supplier) Order status
first product 2200 2500 Not_Shipped
second product 400 400 Not_Shipped
third product 590 600 Not_Shipped
Are there any examples or other help that I can get to do this?
Edit:
Sample Data goes like this
order_products:
order_id product_name product_amount
255 product 1 200
256 product 1 100
257 product 2 50
258 product 3 10
orders:
order_id order_date order_status
255 09.05.2018 Shipped
256 09.05.2018 Shipped
257 10.05.2018 Not_Shipped
258 10.05.2018 Not_Shipped
supplier:
product_name product_amount
product 1 2500
product 2 400
product 3 600

You should use a join on the aggregated subselect.
SELECT t1.product_name, t1.sum_order_products, t2.supplier_sum, t1.order_status
FROM (
SELECT op.product_name, SUM(op.product_amount) sum_order_products, o.order_status
FROM order_products op
INNER JOIN orders o ON op.order_id = o.order_id
WHERE o.order_status = 'Shipped'
GROUP BY op.product_name, o.order_status
) t1
LEFT JOIN (
SELECT s.product_name, SUM(s.product_amount) supplier_sum
FROM supplier s
GROUP BY s.product_name
) t2 ON t1.product_name = t2.product_name
ORDER BY t1.order_status, t1.product_name

From What I understand, I think this is what you want, please give more clarity if this is not what you are expecting.
You will need to use GROUP BY clause and them you will have to use count() function to count the number of rows for the results coming from Group By Clause. I am writing an example of how to use a group by clause, you will need to modify the query as per your need.
SELECT
order_products.product_name,
count(*) as Total_Orders,
MAX(supplier.product_amount) as Supplier_Amt,
orders.order_status
FROM supplier
INNER JOIN order_products ON supplier.product_name = order_products.product_name
INNER JOIN orders ON orders.order_id = order_products.order_id
WHERE orders.order_status = 'Not_Shipped'
GROUP BY order_products.product_name, orders.order_status;
You will need to queries, you can write the other one, just replace WHERE orders.order_status = 'Not_Shipped' with WHERE orders.order_status = 'Shipped' Also if you want all in a single query, simply remove the where clause.

Related

How to get associated row data from min value

I am trying to get the minimum price (totalprice) from a grouped column (sku) and then get the corresponding supplier data (supplier) associated with the resulting lowest price.
Table example
sku supplier totalprice
505 Sup1 20
505 Sup2 30
505 Sup3 25
605 Sup1 100
605 Sup2 97
605 Sup3 111
I am trying to group the sku column and get the lowest price and related supplier,
$query = "SELECT sku, supplier, MIN(totalprice) FROM pricetable GROUP BY sku";
$result = mysqli_query($conn, $query);
while($row = mysqli_fetch_array($result)) {
echo "The cheapest ". $row['sku']. " is £" .$row['MIN(totalprice)']." from ".$row['supplier'];
For example,
group 505 has the lowest price of 20 from supplier Sup1
group 606 has the lowest price of 97 from supplier Sup2
The code above gives me the lowest price for each sku group, but I can't get the associated supplier name with it.
You can try below - using correlated subquery
SELECT sku, supplier, totalprice FROM pricetable t1
where totalprice in
(select MIN(totalprice) from pricetable t2 where t1.sku=t2.sku GROUP BY t2.sku)
In MySQL 8.x you can do:
select *
from pricetable
where rank() over(partition by sku order by totalprice) = 1
Another common way to do this is to create a derived table with the sku and the min totalprice per sku and join back to your base dataset.
SELECT PT.sku, PT.supplier, PT.totalprice
FROM pricetable PT
INNER JOIN (SELECT min(totalprice) MTP, SKU
FROM pricetable
GROUP BY sku) B
on PT.SKU = B.SKU
and PT.MTP = PT.totalprice

Mysql join two tables with sum of quantity

Q : I am trouble to do following task in mysql query.
Task is get all products (If product is duplicate than sum of it's qty) and deduct wastage stock (If wastage product is duplicate than sum of it's qty).
I have two tables like,
1) manage_stock
2) manage_wastage
manage_stock
=> This table has p_id(Product ID) and many rows with product duplication's.
p_id p_name p_qty
1 Pro-1 10
2 Pro-2 15
3 Pro-3 8
1 Pro-1 15
manage_wastage
=> This table has p_id(Product ID) of manage_stock table. It is also many rows with product duplication's.
p_id w_qty
1 2
1 4
3 5
Desired Output
p_id p_name p_qty w_qty final_qty
1 Pro-1 20 6 14
2 Pro-2 15 0 15
3 Pro-3 8 5 3
Thank you very much.
You just have to compute the difference between the stock quantity and the wastage
SELECT s.p_id, s.p_name, SUM(p_qty), SUM(w_qty), SUM(p_qty) - SUM(w_qty) as final_qty
FROM manage_stock s
LEFT OUTER JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_id, s.p_name
try this one
SELECT s.p_id, s.p_name, SUM(p_qty),SUM(ifnull(w_qty, 0)),SUM(p_qty - ifnull(w_qty, 0)) as total
FROM manage_stock s
left outer JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_name
its work
SELECT ms.p_id ,GROUP_CONCAT(ms.p_name)p_name ,SUM(ms.p_qty) p_qty ,SUM(mw.w_qty) w_qty,SUM(ms.p_qty)-SUM(mw.w_qty) final_qty FROM manage_stock ms
INNER JOIN manage_wastage mw on ms.p_id =mw.p_id
GROUP BY ms.p_id
Try above code.
As p_name always unique with p_id GROUP_CONCAT() only returns single name.

Get sum of min values in each group from Mysql

I am trying to retrieve the minimum price of some models.
Each model belongs to a certain group which belongs to a product.
I have the following tables:
Product
model_id product_id price
1 1 100
2 1 120
3 1 100
4 1 200
5 1 250
10 1 20
11 1 50
12 1 50
Product Overview
model_id product_id group_id
1 1 A
2 1 A
3 1 A
4 1 A
5 1 A
10 1 B
11 1 B
12 1 B
Product Group Optional
group_id product_id
B 1
Some groups could be optional, which means price will be zero unless the member wants to choose otherwise.
So in the example above, I want to get the sum of minimum price from each group.
We have two groups, group A and group B.
Group A minimum price value is 100 (model_id 1 and 3)
Group B minimum price value is 20 (model_id 10) but because Group B is optional then that means minimum price value is 0.
Overall sum of min values: 100 (Group A) + 0 (Group B) = 100
My code so far:
SELECT po.group_id,
CASE WHEN
((SELECT COUNT(*) FROM product_group_optional pgo
WHERE po.group_id = group_id AND po.product_id = 1 AND po.product_id = product_id) >= 1)
THEN SUM(0)
ELSE SUM(p.price)
END AS sum_price
FROM product_overview po, product p
WHERE po.product_id = 1
AND po.model_id = p.model_id
AND p.price = (
SELECT MIN(p2.price)
FROM product p2, product_overview po2
WHERE po2.product_id = 1 AND po2.group_id = po.group_id
AND po2.model_id = p2.model_id
)
GROUP BY po.group_id
The output:
group_id sum_price
A 200
B 0
The problem is that I get 200 for Group A but it should be 100.
There are 2 models with min value 100, model 1 and 3. And I assume these are sum together = 100 + 100 = 200.
Issue a) But I want to just take the min value, no matter how many times this value exists.
Issue b) Also, I am trying to get the SUM of those two output SUM of Group A and Group B.
But I am not sure how to do it.
I want it to be done in this query.
Desired output
Sum of all groups
100
Can anyone lead me to the right direction please?
You can use the following query:
SELECT SUM(min_price)
FROM (
SELECT po.group_id,
MIN(CASE WHEN pgo.group_id IS NULL THEN price ELSE 0 END) AS min_price
FROM Product AS p
INNER JOIN Product_overview AS po
ON p.product_id = po.product_id AND p.model_id = po.model_id
LEFT JOIN Product_group_optional AS pgo ON po.group_id = pgo.group_id
GROUP BY po.group_id) AS t
I'm not sure that I understand the keys of your tables, and the problem as well.
There is few questions.
a) The answer should be 120?
b) If the Product has no price, the is price null?
c) If there is a Product in a group with null price and others with price, should it be counted as 0?
Here is how you could get the sum of the lower prices of each group, ignoring the product_group_optional for while:
SELECT t2.group_id, sum(t2.new_price)
FROM
(
SELECT t.group_id, t.new_price
FROM
(
SELECT po.group_id, if(ifnull(pgo.product_id, true), p.price, 0) as new_price
FROM product p, product_overview po
LEFT JOIN product_group_optional pgo ON po.group_id = pgo.group_id
WHERE p.model_id = po.model_id
ORDER by po.group_id, new_price
) t
GROUP BY t.group_id
) t2

Min() with INNER JOIN and Full-text-search

So Ive got the following Query to work just fine, searching for 'test*' in 'products_desc' column and fetching all its prices in the 'prices' table.
SELECT products.id, prices.price, products.product_desc FROM products
INNER JOIN prices
ON prices.product_id = products.id
WHERE
MATCH (products.product_desc) AGAINST ('test*' IN BOOLEAN MODE)
Although the 'prices' table consists of multiple prices per product and I only want to fetch the lowest one to each product. I've previously filtered the prices using
INNER JOIN (
SELECT min(price) as price, prices.product_number as product_number FROM prices
WHERE prices.product_number LIKE'".$q."%'
GROUP BY prices.product_number
) min_prices
on prices.price = min_prices.price
and prices.product_number = min_prices.product_number
but this was when I used products_numbers within the prices table (now there is just a product_id-column.
Products
id | product_desc
----------------------------------------
1 | product1
2 | product2
Prices
id | product_id | price
------------------------------------------------
1 | 1 | 312
2 | 1 | 219
3 | 2 | 312
4 | 2 | 111
Also, the table consists of 10+ million rows so, efficiency matters a lot :)
EDIT
What if I need to access value of columns on the min(prices.price) row?
SELECT products.id, MIN(prices.price) as prices_price, prices.id as prices_id, products.product_desc, products.product_number, prices.supplier_id, suppliers.name FROM products
INNER JOIN prices
ON prices.product_id = products.id
INNER JOIN suppliers
ON prices.supplier_id = suppliers.id
WHERE
MATCH (products.product_desc) AGAINST ('test*' IN BOOLEAN MODE)
GROUP BY prices.product_id
The above returns the lowest price per product but also the wrong value in the other columns?
You can use GROUP BY for this, with MIN() group by function.
GROUP BY is used to group values from a column, and perform calculations on column.
In our case we want to group the result by product_id as it's repeating in second table and perform calculation (min()) on price column of second table.
This is how your Query would look like:
SELECT products.id, MIN(prices.price), products.product_desc FROM products
INNER JOIN prices
ON prices.product_id = products.id
WHERE
MATCH (products.product_desc) AGAINST ('test*' IN BOOLEAN MODE)
GROUP BY prices.product_id

IDs from count query

I have table Orders:
O_Id OrderDate OrderPrice Customer
1 2008/11/12 1000 Hansen
2 2008/10/23 1600 Nilsen
3 2008/09/02 700 Hansen
4 2008/09/03 300 Hansen
5 2008/08/30 2000 Jensen
6 2008/10/04 100 Nilsen
and query:
SELECT COUNT(Customer) AS CustomerNilsen FROM Orders
WHERE Customer='Nilsen'
but is possible add to this results IDs results?
I would like receive
count: 2
and
ids: 2 and 6
GROUP_CONCAT may help:
SELECT
COUNT(Customer) AS CustomerNilsen,
GROUP_CONCAT(O_Id) as IDS
FROM
Orders
WHERE
Customer='Nilsen'
Better to just fetch all the IDs and then use the appropriate row count function:
SELECT `O_Id` FROM `Orders`
WHERE `Customer` = 'Nilsen'
I don't really understand your question, but from what I can tell you just want to SELECT the o_id column in your query:
SELECT COUNT(Customer) AS CustomerNilsen, O_Id AS OrderID FROM Orders WHERE Customer='Nilsen'
You might check this
SELECT Customer,
COUNT(Customer) AS CustomerNilsen
FROM Orders
WHERE Customer = 'Nilsen'
GROUP BY Customer
HAVING CustomerNilsen = 1
Try this
SELECT O1.O_Id AS OrderID,Count(O1.O_Id) AS OrderCount FROM Orders O1
INNER JOIN Orders O2 ON O1.Customer = O2.Customer
WHERE O1.Customer='Nilsen'
GROUP BY O1.Customer,O1.O_Id

Categories