select sum() from multiple table with same column - mysql

I have a table for product, sales_item and a stock with following structure
Product table:
+----+-----+-------------+
| id |name |description |
+----+-----+-------------+
| 1 |Pr1 |prod1 |
+----+-----+-------------+
| 2 |Pr2 |prod2 |
+----+-----+-------------+
| .. |... |..... |
+----+-----+-------------+
sales_item_details table
+-----+----------+------------+-----+
| id | sales_id | product_id | qty |
+-----+----------+------------+-----+
| 517 | 211 | 1 | 200 |
+-----+----------+------------+-----+
| 518 | 211 | 1 | 120 |
+-----+----------+------------+-----+
and production
+----+------------+-------+
| id | product_id | qty |
+----+------------+-------+
| 1 | 1 | 20 |
| 2 | 2 | 200 |
| 3 | 1 | 20 |
| 4 | 3 | 30 |
| 5 | 9 | 30 |
| 6 | 65 | 10 |
| 7 | 65 | 50 |
| 8 | 71 | 10 |
| 9 | 71 | 10 |
| 10 | 71 | 10 |
+----+------------+-------+
And now I am creating multiple database with same table defination and need to maintain stock
production table and product table will be maintained from single database
only sales_item_details table will be different but product id will same
So how will be the query to get SUM(qty) of sales item details and view the inventory in stock
I have tried this:
SELECT
`pr`.`id`,
`pr`.`name`,
sl.size,
IFNULL(SUM(s.qty), 0) AS sales,
IFNULL((SELECT SUM(qty) FROM production st WHERE st.product_id = `pr`.`product-id`), 0) AS stock_added
FROM products pr
LEFT JOIN (
SELECT qty, product_id FROM db1.sales_item_details
UNION ALL
SELECT qty, product_id FROM db2.sales_item_details
) s ON pr.`id` = s.product_id
LEFT JOIN size_list sl ON sl.id = `pr`.`product-size`
GROUP BY s.product_id
ORDER BY sales DESC
but getting the product which is sold
Any help will be appriciated

1st I created a view holding all sales items grouped by product id in the main database:
CREATE OR REPLACE VIEW unit_sold_all AS
SELECT
p.`product-id` AS product_id,
(
(SELECT IFNULL(SUM(s0.qty), 0) FROM db_1.sales_item_details s0 WHERE s0.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s1.qty), 0) FROM db_2.sales_item_details s1 WHERE s1.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s2.qty), 0) FROM db_3.sales_item_details s2 WHERE s2.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s3.qty), 0) FROM db_4.sales_item_details s3 WHERE s3.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s4.qty), 0) FROM db_5.sales_item_details s4 WHERE s4.product_id = p.`product-id`)
) as total_unit_sales
FROM products p
Then in another sql, I selected the sum of the sales.
PS: I answered this question myself because this might need by another person in the future.

Related

SQL Query: join with condition

I have the following tables:
Customer
| c_id | name |
| -------- | -------------- |
| 1 | Adam |
| 2 | Bradley |
| 3 | Chandler |
| 4 | Damian |
| 5 | Eric |
| 6 | Frank |
orders
| order_id | c_id | amount
| -------- | -------------- | -------------- |
| 1 | 1 | 50
| 2 | 1 | 2
| 3 | 2 | 15
| 4 | 2 | 22
| 5 | 2 | 10
| 6 | 2 | 7
| 7 | 3 | 7
| 8 | 3 | 2
| 9 | 5 | 18
| 10 | 5 | 24
| 11 | 6 | 60
| 12 | 6 | 1
I want to create a list of users who have order amounts over 50.
This list should include c_id, name and the sum of all their orders including those under 50.
so it should look like this:
| c_id | name | amount
| -------- | -------------- | -------------- |
| 1 |Adam | 52
| 6 | Frank | 61
You can use group by and having:
select c.c_id, c.name, sum(o.amount)
from orders o join
customers c
on o.c_id = c.c_id
group by c.c_id, c.name
having max(o.amount) > 50;
SELECT
c_id
, name
, SUM(amount) AS total_amount
FROM
orders a
INNER JOIN customer b
ON b.c_id = a.user_id
WHERE
c_id IN (
SELECT
user_id
FROM
orders
WHERE
amount >= 50)
GROUP BY c_id, name
Best to break this down into chunks:
Customers who have a total amount over 50:
SELECT user_id FROM orders GROUP BY user_id HAVING sum(amount) >= 50;
Sum of the amounts for each order for customers that meet the criteria above:
SELECT user_id, sum(amount) as order_total
FROM orders
WHERE user_id IN (SELECT user_id FROM orders HAVING sum(amount) >= 50 GROUP BY user_id)
GROUP BY user_id;
You can just join over to your customer table to grab the name. Didn't include since that is the more straightforward ask here.

Update several records with the sum of several records from another table - mysql

I have the following table:
product
+-------------+------------+
| id_product | quantity |
+-------------+------------+
| 15 | 0 |
| 16 | 1 |
| 17 | 3 |
| 18 | 1 |
+-------------+------------+
And the other table is a subquery
+------------+-----------+
| id_product | total |
+------------+-----------+
| 15 | 1 |
| 17 | 1 |
| 18 | 4 |
+------------+-----------+
And I want to do is in a single update query, update the table products with the records returned by the subquery, making a sum, I can get one or many records from the subquery.
+-------------+------------+
| id_product | quantity |
+-------------+------------+
| 15 | 1 |
| 16 | 1 |
| 17 | 4 |
| 18 | 5 |
+-------------+------------+
I tried to make this update query, but it does not do what I want.
UPDATE product p
INNER JOIN (
SELECT id_product, count(*) as total
FROM othertable
GROUP BY id_product
) c ON p.id_product = c.id_product
SET p.quantity = c.total;
______EDIT______
UPDATE product p
INNER JOIN (
SELECT id_product, count(*) as total
FROM othertable
GROUP BY id_product
) c ON p.id_product = c.id_product
SET p.quantity = p.quantity + c.total

Implementing a complex query in MySQL

I have 3 tables:
table products
table sub products
table stock.
I want to join these tables like in the result table below. In fact, I want All products that have least price and have count greater than zero and inserted as latest records!
How can I do the query?
more explain:
table product
----------------------------------
pid | title | desc | content |
----------------------------------
1 | lumia 920| ..... | ...... |
----------------------------------
2 | galaxys6 | .... | ...... |
----------------------------------
table sub_product
------------------------
subid |pid| name |
------------------------
1 | 1 | yellow |
------------------------
2 | 1 | black |
------------------------
3 | 2 | 32 GB |
table stock
-----------------------------------------------
sid |subid| price | count | inserted_date |
-----------------------------------------------
1 | 1 | 100 | 5 | 2015-01-01 |
-----------------------------------------------
2 | 1 | 150 | 9 | 2015-01-02 |
-----------------------------------------------
3 | 1 | 100 | 0 | 2015-02-02 |
-----------------------------------------------
4 | 2 | 111 | 1 | 2015-02-21 |
-----------------------------------------------
5 | 3 | 50 | 7 | 2015-02-01 |
-----------------------------------------------
6 | 3 | 10 | 4 | 2015-03-06 |
-----------------------------------------------
7 | 3 | 400 | 9 | 2015-06-06 |
-----------------------------------------------
table result
------------------------------------------------------------
pid |subid| title | name | price | count | inserted_date
------------------------------------------------------------
1 | 2 |lumia 920| black | 111 | 1 | 2015-02-21
------------------------------------------------------------
2 | 3 |galaxy s6| 32 GB | 10 | 4 | 2015-03-06
------------------------------------------------------------
as you see in product table we have two items lumia 920 and galaxy s6
and in sub_product we have 3 items that related to products.
also in stock I saved all modication of price and count of each item
so I want return latest modification of each sub_product as current state of it sub_prodct that has least price as result
but if count was zero should return another sub_product with mentioned conditions.
Select * From stock s Join sub_product sp On s.sub_productid = sp.sub_productid Join product p On p.productid = sp.productid
Where s.counte > 0 And s.date_insert in (Select MAX(date_insert) as d From stock ss
where s.sub_productid = ss.sub_productid group by sub_productid)
This query will return the all products that have least price and have count greater than 0 and latest records.
SELECT p.pid, sp.subid, p.title, sp.name, s.price, s.count, s.inserted_date
FROM product p
INNER JOIN sub_product sp ON sp.pid = p.pid
INNER JOIN stock s ON s.subid = sp.subid
WHERE s.count > 0
GROUP BY p.title
ORDER BY s.inserted_date DESC, s.price ASC
Try something like this:
SELECT prod.title, prod.desc, subProd.spid, subProd.pid, subProd.name, stk.price, stk.discount, stk.count, stk.inserted_date
FROM products AS prod
INNER JOIN sub_products AS subProd ON prod.pid = subProd.pid
INNER JOIN stock AS stk ON subProd.spid = stk.spid
AND stk.count > 0
AND stk.spid = (select spid from stock order by inserted_date desc limit 1)

SQL Server : Many to Many

I have a many to many relationship, Orders, OrderProducts, and Products. I need a query that gives me a list of products that are NOT in ALL orders, but has been ordered.
______________________
| ORDERS |
_______________________
| OrderID | OrderDate |
| 1 | 1/2/2012 |
| 2 | 1/3/2012 |
| 3 | 1/4/2012 |
| 4 | 1/5/2012 |
| 5 | 1/6/2012 |
______________________
| ORDERPRODUCTS |
_______________________
| OrderID | PRODUCTID |
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 5 |
| 4 | 1 |
| 5 | 1 |
__________________________
| PRODUCTS |
__________________________
| PRODUCTID | PRODUCTNAME |
| 1 | Widget 1 |
| 2 | Widget 2 |
| 3 | Widget 3 |
| 4 | Widget 4 |
| 5 | Widget 5 |
| 6 | Widget 6 |
In the provided example, notice that product 1 is in all orders and product 6 is not ordered at all.
I need a query that returns Products 2, 3, 4, and 5.
Also keep in mind that while there aren't many products, there are a few hundred thousand orders in the live database.
SELECT PRODUCTID
FROM ORDERPRODUCTS
GROUP BY PRODUCTID
HAVING COUNT(DISTINCT OrderID) < (SELECT COUNT(*) FROM ORDERS )
It's Saturday night, so this is probably not the most elegant, but here's one try:
DECLARE #OrderProducts TABLE(OrderID INT, ProductID INT);
DECLARE #Products TABLE(ProductID INT, ProductName VARCHAR(32));
INSERT #Products VALUES
(1,'Widget 1'),(2,'Widget 2'),
(3,'Widget 3'),(4,'Widget 4'),
(5,'Widget 5'),(6,'Widget 6');
INSERT #OrderProducts VALUES
(1,1),(1,2),(2,1),(2,2),(2,3),
(2,4),(3,1),(3,5),(4,1),(5,1);
SELECT p.ProductID, p.ProductName
FROM #Products AS p
WHERE EXISTS -- had been ordered at least once
(
SELECT 1 FROM #OrderProducts
WHERE ProductID = p.ProductID
)
AND EXISTS -- at least one order does NOT include it
(
SELECT 1 FROM #OrderProducts AS o
WHERE NOT EXISTS
(
SELECT 1 FROM #OrderProducts AS o2
WHERE o2.OrderID = o.OrderID
AND o2.ProductID = p.ProductID
)
);
SELECT
DISTINCT
PossibleOrderProducts.PRODUCTID
FROM
(
SELECT
Orders.ORDERID,
Products.PRODUCTID
FROM
ORDERS Orders
CROSS JOIN
(
SELECT DISTINCT PRODUCTID FROM ORDERPRODUCTS
) Products
) PossibleOrderProducts
LEFT JOIN ORDERPRODUCTS ActualOrderProducts ON
ActualOrderProducts.ORDERID = PossibleOrderProducts.ORDERID
AND ActualOrderProducts.PRODUCTID = PossibleOrderProducts.PRODUCTID
WHERE
ActualOrderProducts.ORDERID IS NULL

Return distinct and null records from a mysql join query

Is there any way to return distinct values with blank/null data from a table join. Best to explain with my example below.
Table "orders"
order_id | order_total
1 | 10
2 | 20
3 | 50
Table "order_items"
item_id | order_id | name | qty_ordered | base_price | row_total
1 | 1 | Product | 1 | 10 | 10
2 | 2 | Product | 1 | 10 | 10
3 | 2 | Product2 | 1 | 10 | 10
4 | 3 | Product | 2 | 10 | 20
5 | 3 | Product2 | 3 | 10 | 30
I'm trying to produce a result set that looks like this.
order_id | item_id | name | qty_ordered | base_price | row_total | order_total
1 | 1 | Product | 1 | 10 | 10 | 10
2 | 2 | Product | 1 | 10 | 10 | 20
null | 3 | Product2 | 1 | 10 | 10 | null
3 | 4 | Product | 2 | 10 | 20 | 50
null | 5 | Product2 | 3 | 10 | 30 | null
I only want the order_id and order_total once per order. I figure this is possible with some sort of join/distinct/sub query but alas nothing I've tried has worked so far.
Use:
SELECT x.order_id,
x.item_id,
x.name,
x.qty_ordered,
x.base_price,
x.row_total,
x.order_total
FROM (SELECT CASE
WHEN #order = o.order_id THEN NULL
ELSE o.order_id
END AS order_id,
oi.item_id,
oi.name,
oi.qty_ordered,
oi.base_price,
oi.row_total,
o.order_total,
CASE
WHEN #order = o.order_id THEN NULL
ELSE o.order_total
END AS order_total,
#order := o.order_id
FROM ORDER_ITEMS oi
JOIN ORDERS o ON o.order_id = oi.order_id
JOIN (SELECT #order := -1) r
ORDER BY o.order_id, oi.item_id) x
SELECT * FROM order_items
LEFT JOIN orders
ON (
order_items.order_id=orders.order_id
AND
order_items.item_id=(
SELECT MIN(item_id)
FROM order_items a
WHERE a.order_id=order_items.order_id
)
)
This should work because the nested query always returns the same MIN(item_id) for each order, and it only joins for that item.
But this is a very, very ugly piece of sql. Don't do this.