MYSQL count related rows in 2 tables - mysql

I have 3 tables
products table
productid productname
--------- -----------
1 product 1
2 product 2
5 product 3
10 product 4
11 product 5
12 product 6
accounts_products table
id productid accountid
-- --------- ---------
1 1 accountid 1
2 10 accountid 2
3 2 accountid3
leads_products table
id productid leadid
-- --------- ---------
1 1 leadid 1
2 5 leadid 2
3 2 leadid 3
I am trying to count how many total products are in leads_products and accounts_products tables based on the same productid's.
Expected result
Product ID Product Name Total
----------- ------------ --------
1 product 1 2
2 product 2 2
5 product 3 1
10 product 4 1
I tried so far
SELECT p.productid as 'Product ID',
p.productname as 'Product Name',
COUNT(*) as 'Total' FROM products p
INNER JOIN leads_products l ON (l.productid=p.productid)
INNER JOIN accounts_products a ON (a.productid=p.productid)
GROUP BY p.productname,p.productid
Above query counts and display higher number than expected.
I hope it makes sense.

Try this:
SELECT p.productid as 'Product ID',
p.productname as 'Product Name',
(SELECT COUNT(*)
FROM leads_products AS l
WHERE l.productid = p.productid) +
(SELECT COUNT(*)
FROM accounts_products AS a
WHERE a.productid=p.productid) AS 'Total'
FROM products AS p
http://www.sqlfiddle.com/#!2/f8472/5
Alternative approach using JOIN (better performance):
SELECT p.productid as 'Product ID',
p.productname as 'Product Name',
IFNULL(l.count, 0) + IFNULL(a.count, 0) as 'Total'
FROM products AS p
LEFT JOIN (
SELECT productid, COUNT(*) AS count
FROM leads_products
GROUP BY productid
) AS l
ON l.productid = p.productid
LEFT JOIN (
SELECT productid, COUNT(*) AS count
FROM accounts_products
GROUP BY productid
) AS a
ON a.productid = p.productid
http://www.sqlfiddle.com/#!2/f8472/33

I did it with a left join of p.products to preserve all the products then counted the products in each list and added them together. Worked first try. There's probably a billion ways to do this.
SELECT p.productid 'Product ID',
p.productname 'Product Name',
COUNT(a.accountid) + COUNT(l.leadid) total
FROM products p
LEFT JOIN accounts_products a ON p.productid = a.productid
LEFT JOIN leads_products l ON p.productid = l.productid
GROUP BY p.productid
http://www.sqlfiddle.com/#!2/f8472/37

Related

Query using case and update the last record

I have two tables
oc_stock_hpp
id product_id stock
2 1234 0
3 5678 6
4 1234 2
6 1234 3
9 5678 7
oc_product
id product_id quantity
1 1234 7
23 5678 9
My purpose is to update the difference value (between SUM(stock) and quantity) in the stock field table oc_stock_hpp.
If the SUM(stock) > quantity then subtract the difference from the last record of stock
If the SUM(stock) > quantity then add the difference from the last record of stock
so the result will be like this
id product_id stock
2 1234 0
3 5678 6
4 1234 2
6 1234 5
9 5678 3
I have tried this but error
CASE
WHEN SUM(shpp1.stock) > p.quantity
THEN UPDATE oc_stock_hpp shpp1 INNER JOIN oc_product p ON shpp1.product_id = p.product_id
SET shpp1.stock = (shpp1.stock - ((SELECT SUM(shpp2.stock) FROM oc_stock_hpp shpp2 LEFT JOIN oc.product p WHERE shpp2.product_id = p.product_id) - p.quantity)
WHERE shpp1.id = (SELECT MAX(id) FROM (SELECT * FROM oc_stock_hpp) o1 WHERE product_id = p.product_id)
WHEN SUM(shpp1.stock) < p.quantity
THEN UPDATE oc_stock_hpp shpp1 INNER JOIN oc_product p ON shpp1.product_id = p.product_id
SET shpp1.stock = (shpp1.stock + (p.quantity - (SELECT SUM(shpp2.stock) FROM oc_stock_hpp shpp2 LEFT JOIN oc.product p WHERE shpp2.product_id = p.product_id))
WHERE shpp1.id = (SELECT MAX(id) FROM (SELECT * FROM oc_stock_hpp) o1 WHERE product_id = p.product_id)
END
FROM oc_product p
LEFT JOIN oc_stock_hpp shpp ON shpp.product_id = p.product_id
Join the 2 tables to a query that returns the last id and total stock for each product:
UPDATE oc_stock_hpp s
INNER JOIN oc_product p ON p.product_id = s.product_id
INNER JOIN (SELECT MAX(id) id, SUM(stock) stock FROM oc_stock_hpp GROUP BY product_id) t ON t.id = s.id
SET s.stock = s.stock + p.quantity - t.stock;
See the demo.

php - Check same column twice in mysqli query

I have 3 tables in my php based system.
Those tables are product, category, product_categories.
Product
pid | product_name | price
1 | Nike T-Shirt | 23
Category
cid | category_name
1 | Men
2 | Women
Product_categories
pcid | cid | pid
1 | 1 | 1
2 | 2 | 1
That means, 1 product may be in both multiple categories.
Now I am developing the product search section with filter.
If a user select both categories, all the products in selected categories should display.
Example : If a user select both Men & Women, Nike T-Shirt should be displayed.
The query I used:
select p.*
from products p
left join product_categories pc on pc.pid=p.pid
WHERE pc.cid ='1' AND pc.cid = '2'
But it not returning correct products.
Where is the error?
You want conditions that span over multiple rows, which suggests aggregation. You can join the tables, group by product, and use the having clause for filtering:
select p.id, p.product_name, p.price
from product p
inner join product_category pc on pc.pid = p.pid
inner join category c on c.cid = pc.cid
where c.category_name in ('Men', 'Women')
group by p.pid, p.product_name, p.price
having max(c.category_name = 'Men') = 1 and max(c.category_name = 'Women') = 1
If you can filter by category id rather than by category name, then you need one less join:
select p.id, p.product_name, p.price
from product p
inner join product_category pc on pc.pid = p.pid
where pc.cid in (1, 2)
group by p.pid, p.product_name, p.price
having max(pc.cid= 1) = 1 and max(pc.cid = 2) = 1
Here are few alternatives:
-- All products that are at lest in one of the desired categories
select * from product where product.pid = any (select product_category.pid from product_category where cid = 1 or cid = 2);
-- Products that are in both categories
select * from product where product.pid = any (
select product_category.pid from product_category where cid = 1 or cid = 2 group by pid having count(cid) = 2
);
-- Products with additional information "in how many desired categories they are"
-- You can order by it and/or filter on it
with product_category_matches as (
select pid, count(*) as category_count from product_category where cid in (1, 2) group by pid
)
select *, product_category_matches.category_count from
product inner join product_category_matches on product.pid = product_category_matches.pid
where product_category_matches.category_count > 0 -- Product must be at least in one desired category
order by product_category_matches.category_count desc

Select count of total products as well as out of stock products from table

I have to 3 tables: product, product_to_store, store
product table
id quantity status
1 1 1
2 0 1
3 0 1
4 23 1
product_to_store table
store_id product_id
1 1
2 2
1 3
2 4
store table
id name
1 store1
2 store2
To find total products I can run query to fetch all products in table product where status of product is enabled.
select count(*) from product where status=1
total name
2 Store 1
2 store 2
To find total out of stock products I can run below query after joining all 3 tables and using group by store_id:
Select count(*) as outofproducts from product where quantity=0;
Result come like this:
outofproducts name
1 Store 1
1 store 2
But I want combination of above 2 results in single query like below:
outofproducts total name
1 2 Store 1
1 2 store 2
You'd use conditional aggregatiopn, i.e. sum/count over conditions:
select
s.name,
sum(p.quantity > 0) as in_stock,
sum(p.quantity = 0) as out_of_stock,
count(*) as total
from store s
join product_to_store ps on ps.store_id = s.id
join product p on p.id = ps.product_id
group by s.name
order by s.name;
This makes use of MySQL's true = 1, false = 0. If you don't like it, replace sum(p.quantity = 0) with sum(case when p.quantity = 0 then 1 else 0 end) or count(case when p.quantity = 0 then 1 end).
You can start query from store table so that we will get total rows as store table data.
Then use nested query for each store to get out of product and total product count
select
(Select count(*) as outofproducts from product_to_store ps inner join product p on p.id = ps.product_id where quantity=0 and ps.store_id = s.id ) as outofproducts ,
(Select count(*) as count from product_to_store ps inner join product p on p.id = ps.product_id where ps.store_id = s.id ) as totalCount,
s.name
from store s
You could join the related subquery for count
select t1.name, t1.outofproducts, t2.total
from(
select b.id, b.name , count(*) outofproducts
from product_to_store c
inner join product a on a.id = c.product_id
inner join store b on a.id = c.store_id
where a.quantity = 0
group by b.id, b.name
) t1
inner join (
select b.id, b.name , count(*) total
from product_to_store c
inner join product a on a.id = c.product_id
inner join store b on a.id = c.store_id
group by b.id, b.name
) t2 on t1.id = t2.id

Select sold and unsold products

I'm trying to select all products names and how many has been sold in current date, but I'm having a problem since not all products are sold everyday. (When the product has not been sold it must return 0)
TABLE PRODUCTS
ID NAME
1 APPLE
2 PINEAPPLE
3 COFFE
TABLE SALES
ID DATE
1 2014-01-13
2 2014-01-13
TABLE PRODUCTS_AND_SALES
SALE_ID PRODUCT_ID AMOUNT
1 3 2
1 1 1
2 3 1
What I expect to receive:
PRODUCT AMOUNT
APPLE 1
PINEAPPLE 0
COFFE 3
What I receive:
PRODUCT AMOUNT
APPLE 1
COFFE 3
My query:
select product, sum(amount) from products
join products_and_sales using (product_id)
join sales using (sale_id)
where date(dt_sale) = curdate()
group by product_id;
try this
select name as PRODUCT , ifnull(sum(AMOUNT),0) amount from products p
left join PRODUCTS_AND_SALES ps
on p.id = ps.PRODUCT_ID
group by product
DEMO HERE
EDIT:
if you wanna use specefic date then use this
select name as PRODUCT ,if(date = '2014-01-13' ,ifnull(sum(AMOUNT),0), 0 ) amount
from products p
left join PRODUCTS_AND_SALES ps on p.id = ps.PRODUCT_ID
left join SALES s on s.id = ps.SALE_ID
group by product
DEMO HERE
just replace this date 2014-01-13 by the date you want. (curdate()) or what ever
Use OUTER JOIN instead of INNER JOIN
if you show the query you use we will correct it for you.
Try this...
SELECT pr.NAME, IFNULL(SUM(prs.AMOUNT), 0)
FROM PRODUCTS pr
LEFT OUTER JOIN PRODUCTS_AND_SALES prs ON pr.id = prs.product_id
LEFT OUTER JOIN SALES sl ON sl.id = prs.sales_id AND date(s1.dt_sale) = curdate()
GROUP BY pr.NAME

Join two table. One column using SUM

I need a little help with a MySQL query.
I have two tables one table is a list of product and one table is a list of warehouses quantity
product:
product_id product_name
1 name1
2 name2
3 name3
warehouse_product
id warehouse_id product_id product_quantity
1 1 1 15
2 2 1 30
3 1 2 100
4 2 2 30
5 1 3 20
6 2 3 40
The results Im looking to get from the above data would be
product_id product_name product_quantity
1 name1 45
2 name2 130
3 name3 60
I've tried many query but it's not working. My query is:
SELECT
product_id as product_id, SUM(quantity) as quantity
FROM
(SELECT
p.product_id as product_id, wp.product_quantity as quantity
FROM
product as p
LEFT JOIN warehouse_product as wp ON p.product_id = wp.product_id
WHERE
product_active = 1)
Try this:
SELECT p.product_id, p.product_name, SUM(wp.quantity) as quantity
FROM product as p
LEFT JOIN warehouse_product as wp
ON p.product_id = wp.product_id
AND product_active = 1
GROUP BY p.product_id, p.product_name
After JOINing the two tables you need to use GROUP BY so that SUM of quantity can be calculated for each product.
select p.product_id,p.product_name,sum(product_quantity) as 'product_quantity'
from product p inner join warehouse_product whp on
whp.product_id=p.product_id group by whp.product_id
select p.product_id, p.product_name,sum(w.product_quantity)
from
product p
inner join
warehouse_product w
on
p.product_id = w.product_id
group by w.product_id
order by p.product_name;
SELECT P.productid,
P.ProductName,
Sum(W.product_quantity) As quantity
FROM Product AS P
LEFT JOIN warehouse_product AS W
ON P.productid = W.productid
GROUP BY P.ProductId , P.ProductName
SQLFiddle