mysql count, distinct, join? Confusion - mysql

i have 2 tables:
tblItems
ID | orderID | productID
1 1 2
2 1 2
3 2 1
4 3 2
tblProducts
productID | productName
1 ABC
2 DEF
im attempting to find the most popular Product based on whats in "tblItems", and display the product Name and the number of times it appears in the tblItems table.
i can get mysql to count up the total like:
$sql="SELECT COUNT(productID) AS CountProductID FROM tblItems";
but i can't figure out how to join the products table on..if i try LEFT JOIN the query goes horribly wrong
hopefully thats not too confusing..thankss

Are you simply trying to find the count of orders by product like so:
Select P.ProductName, Count(*)
From tblItems As I
Join tblProducts As P
On P.ProductId = I.ProductId
Group By P.ProductName

I think you may be looking for something like:
SELECT tblProducts.productName, COUNT(tblItems.ID)
FROM tblProducts
LEFT JOIN tblItems USING(productID)
GROUP BY tblProducts.productID

SELECT count(i.productID) AS cnt, p.productName FROM tblItems AS i
LEFT JOIN tblProducts AS p ON p.productID = i.productID
GROUP BY i.productID
ORDER BY cnt desc

Related

Write query without join and using subquery

I want to rewrite the join query with sub-query like IN(), ANY() operator.
Data set:
*categories*
categoryID name
5 ROD
7 CEMENT
*products*
productID categoryID name
7 5 BSRM 10mm
9 5 KSRM 5mm
10 5 Julius
11 7
12 5 BSRM 25mm
*sale_products*
saleID productID
118 9
119 9
120 9
121 9
122 12
123 12
124 12
This is my query to read saleID, product name and category name for which already have sold.
My query is:
SELECT sale_products.saleID, products.name, categories.name
FROM categories
INNER JOIN (products, sale_products)
ON categories.categoryID = products.categoryID
AND products.productID = sale_products.productID
Now I want to the result set without join and with the sub-query methodology.
I try in this way:
SELECT categories.name
FROM categories
WHERE categories.categoryID IN
(SELECT products.categoryID
FROM products
WHERE products.productID in
(SELECT sale_products.productID FROM sale_products))
this query only give me the category name but I need also saleID, product name.
Your original query looks queer. Why do you cross join products and sale_products?
It should better be:
select sp.saleid, p.name as product, c.name as category
from sale_products sp
join products p on p.productid = sp.productid
join categories c on c.categoryid = p.categoryid;
This is the straight-forward way to show the data. You can use subqueries instead, but I see no sense in it:
select
sp.saleid
(
select p.name
from products p
where p.productid = sp.productid
) as product,
(
select c.name
from categories c
where c.categoryid = p.categoryid
) as category
from sale_products sp;
Here is yet another query with subqueries. Again without any benefit over the simple query using direct joins on the tables.
select sp.saleid, p.name as product, c.name as category
from sale_products sp
join (select productid, name from products) p on p.productid = sp.productid
join (select categoryid, name from categories) c on c.categoryid = p.categoryid;

mysql joins where unique row required

I have 2 mysql tables : products and product_images.
products:
product_id price discount product_name
---------------------------------------------------
1 10.00 1.0 product 1
2 20 1.0 product 2
product_images:
product_id images
--------------------------
1 image 1
1 image 2
1 image 3
2 image 1
etc....
I need to select each product_id, price,discount,product_name and only the first image from Product_images. Joins are producing the same product_id repeated with multiple images..
How can i write a query for the same so that product_id is unique with only first image from product_images table ???
try that :
select p.`product_id`, `price`, `discount`, `product_name`,`images`
from products p
inner join product_images pi On p.`product_id` = pi.`product_id`
Where stock_status = 'stock' AND status = 'Enabled'
group by p.`product_id`
DEMO
Yes, you can do this with an aggregate query that takes the "first" image.
SELECT a.product_id, a.price, a.discount, a.product_name, MIN(b.image) AS image
FROM products AS a
LEFT JOIN product_images AS b ON a.product_id = b.product_id
GROUP BY a.product_id, a.price, a.discount, a.product_name
The trick here is that the aggregate MIN() function will find the "first" image.
Something like this?
SELECT p.*,GROUP_CONTACT( pi.images )
FROM product p
LEFT JOIN product_images pi ON pi.product_id = p.product_id
GROUP BY p.product_id
This will give you a comma-separated list of all the images for the product. The problem I see here is you don't seem to currently have a way of defining the "first" image for a product. Maybe you need to add an order column to your product_images table?
As discussed on the comments, here is the query you need:
select product_id, price, discount, product_name, image
from
(select p.product_id,
p.price,
p.discount,
p.product_name,
min(pi.id) im_id
from products p
inner join products_image pi
on (p.product_id=pi.product_id)
group by p.product_id,
p.price,
p.discount,
p.product_name ) pd
inner join
products_image pimg on ( pd.im_id = pimg.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

MySQL join table return only one match

I'm struggling the the JOIN in a MySQL query. Somehow I can't find out why my result is not what I want.
I have two tables, a table orders and a table products. The table product holds the order.id of the order. So a order can have more than one products, so for example the table products holds two records for a order.
The result I need is all orders where a product holds a VAT of 21.
Table example.
orders
id | customer
---------------
1 | John Doe
2 | Hello World
order_products
id | order_id | product | vat
1 | 1 | Porsche 911 GT4 | 21
2 | 1 | Audi R8 LMS | 21
3 | 1 | Ferrari Enzo | 19
3 | 2 | Bugatti Veyron | 19
No I want all orders where the products have a VAT of 21. So I will do a LEFT JOIN on the table order_products:
SELECT orders.id, orders.customer, order_products.product FROM orders LEFT JOIN order_products ON orders.id = order_products.order_id WHERE order_products.vat = '21'
This returns the following:
1 John Doe Porsche
1 John Doe Audi R8 LMS
But I only need one result because the orders.id is important for me, not all products in the order. I only join on the order_products to get the orders with only VAT 21. At the moment I ran out of options on how to fix this. Even after reading several topics about joins on this site and other sites.
First, you aren't going to return any orders that don't have products, so there is no need for a left join...an inner join is fine.
If the orders_product is not important to you, you can use a subquery and not select any columns from the orders_product. With your current query, you're selecting a column though.
Something like...
SELECT id, customer
FROM orders
WHERE order_id IN (SELECT order_id FROM order_products
WHERE order_products.vat = '21');
If you prefer not to use a correlated subquery, you can use a group by or distinct
SELECT orders.id, orders.customer
FROM orders
INNER JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id, orders.customer;
or...
SELECT DISTINCT orders.id, orders.customer
FROM orders
INNER JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21';
If you only care about the orders then you can group by the order id:
SELECT orders.id, orders.customer, order_products.product
FROM orders
LEFT JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id;
However note that order_products.product will only be one of the products. If you wish to display all of the products but in the one column you can user GROUP_CONCAT:
SELECT orders.id, orders.customer, GROUP_CONCAT(order_products.product)
FROM orders
LEFT JOIN order_products ON orders.id = order_products.order_id
WHERE order_products.vat = '21'
GROUP BY orders.id;
This will return:
1 John Doe Porsche, Audi R8 LMS
SELECT DISTINCT o.id
, o.customer
FROM orders o
JOIN order_products op
ON op.order_id = o.id
WHERE op.vat = 21;