I have the following query, where i want to get the total number of rows but this seems to count each individually here is the query and the result
SELECT
COUNT(pc.product_id)
FROM
products as p
INNER JOIN product_categories as pc
ON p.product_id = pc.product_id AND pc.subcategory_id IN (77)
GROUP BY pc.product_id
HAVING COUNT(pc.subcategory_id) = 1
Result is :
COUNT(pc.product_id)
1
1
1
...but it should be
COUNT(pc.product_id)
3
UPDATE
the above query should count the number of products that are get by this query
SELECT
*
FROM
products as p
INNER JOIN product_categories as pc
ON p.product_id = pc.product_id AND pc.subcategory_id IN ($sb_2)
GROUP BY pc.product_id
HAVING COUNT(DISTINCT pc.subcategory_id) = $sb_count
$sb_2 = 77,76;
$sb_count = how many values are in $sb_2;
77 and 76 are different subcategories ids but are common for some products
If you know another way to count this or to make another query...
SELECT
COUNT(pc.product_id)
FROM
products as p
INNER JOIN product_categories as pc
ON p.product_id = pc.product_id AND pc.subcategory_id IN (77)
HAVING COUNT(pc.subcategory_id) = 1
Removing the group by should do the trick.
I manage to count rows by the following query.
"SELECT COUNT(*) as count FROM (SELECT
*
FROM
product_categories WHERE subcategory_id IN (77,76)
GROUP BY product_id
HAVING COUNT(DISTINCT subcategory_id) = 2) as subc";
}
Related
This query gives an error if subquery return more than 1 row. I separated the queries and use mysqli_multi_query(), but both queries data is displayed in two tables.
So I decided to make the one query.
SELECT DISTINCT category ,
(SELECT COUNT(products.name)
FROM products
where category_id=categories.id
) AS total_products,
(
SELECT SUM(quantity) FROM productstock a
LEFT JOIN products b ON a.product_id=b.id
LEFT JOIN categories c ON b.category_id=c.id
where c.deleted=0
GROUP BY category_id
) AS available_stock,
SUM(product_qty*orignalCost) AS SaleWise_cost,
SUM(product_qty*saleprice) AS SaleWise_price,
SUM(product_qty*saleprice) AS total_sale ,
SUM((product_qty*saleprice)-(product_qty*orignalCost)) AS profit
FROM categories
INNER JOIN products ON categories.id = products.category_id
INNER JOIN sales ON sales.product_id = products.id
INNER JOIN productstock ON productstock.product_id = products.id
WHERE categories.deleted=0
GROUP BY category_id
As available stock is corelated subquery so joining condition must be added in where clause inside subquery. please check this pseudocode
(
SELECT SUM(quantity) FROM productstock a
LEFT JOIN products b ON a.product_id=b.id
LEFT JOIN categories c ON b.category_id=c.id
where c.deleted=0 AND b.category_id = categories.id
) AS available_stock
Another way
(SELECT SUM(quantity)
FROM products b
INNER JOIN productstock a
ON b.id = a.product_id
AND b.id = products.id
AND b.category_id = categories.id) AS available_stock
I'm having some problems to get this query works as I expect.
I have three tables: products, product_attributes and attributes.
The relation is obvious (A product can have multiple attributes)
products
---------
id
product_attributes
------------------
product_id
attribute_id
attributes
----------
id
name
What I want to achieve is to get those products that has a given list of attributes, BUT omit those products that only has a partial list of the desired attributes.
For example, having these products and attributes:
Shoe 1 [blue,boy]
Shoe 2 [blue,girl]
Shoe 3 [red,boy]
Shoe 4 [red,girl]
A query asking for those products with [blue,boy] would retrieve only Shoe 1.
A query asking for those products with [blue] would not return anything.
Since now I was working with this query:
SELECT p.*, pa.attribute_id
FROM products AS p
LEFT JOIN product_attributes AS pa ON(pa.product_id=p.id)
WHERE
pa.attribute_id IN(' . implode(',', $attr_ids) . ')
GROUP BY p.id
HAVING count(pa.attribute_id)=' . count($attr_ids)
This fails when just an attribute is given because it will return any product having that attribute.
-- PHP (or any other languaje) parts are hardcoded here!!!!
SELECT p.*, hma.howmuchattr
-- howmuchattr is needed by HAVING clause,
-- you can omit elsewhere (by surrounding SELECT or by programming languaje)
FROM products AS p
LEFT JOIN product_attributes AS pa ON pa.product_id = p.id
LEFT JOIN (
SELECT product_id, count(*) as howmuchattr
FROM product_attributes
GROUP BY product_id
) as hma on p.id = hma.product_id
WHERE
pa.attribute_id IN
(1,3) -- this cames from PHP (or any other languaje). Can be (1) for the other case
GROUP BY p.id
HAVING count(*) = howmuchattr;
see sqlfiddle here
see also this answer
Aside from any other issues, this query...
SELECT p.*
, pa.attribute_id
FROM products p
LEFT
-- OUTER (this keyword is optional in MySQL)
JOIN product_attributes pa
ON pa.product_id = p.id
WHERE pa.attribute_id IN('$attr_ids')
GROUP
BY p.id
HAVING COUNT(*) = $cnt;
... is logically identical to...
SELECT p.*
, pa.attribute_id
FROM products p
-- INNER (this keyword is also optional in MySQL)
JOIN product_attributes pa
ON pa.product_id = p.id
WHERE pa.attribute_id IN('$attr_ids')
GROUP
BY p.id
HAVING COUNT(pa.attribute_id) = $cnt;
In order to maintain the utility of the OUTER JOIN consider rewriting as follows...
SELECT p.*
, pa.attribute_id
FROM products p
LEFT
JOIN product_attributes pa
ON pa.product_id = p.id
AND pa.attribute_id IN('$attr_ids')
GROUP
BY p.id
HAVING COUNT(pa.attribute_id) = $cnt;
I'm very new to MySQL and PHP and I'm struggling with inner joins between two tables. I'm constructing a script that reads an os commerce database and tells me which products is currently on back order. In order for the product to be on back order a value in the products_attributes table is set to '134', however it only reads the product_id and not the product_model which is in the 'products' table.
products_attributes(table name)
options_values_id
product_id
products(table name)
product_id
product_model
I want to select items that have the value of '134' in the products_attributes table then match the product_ids from both tables to get the product_model from the "products" table. I feel like the code is very easy but for some reason I'm struggling with how to construct the query and to display it.
SELECT product_model FROM products as p,products_attributes as pa WHERE p.product_id = pa.product_id and pa.options_values_id = 134
or
SELECT p.product_model FROM products p INNER JOIN products_attributes as pa ON (p.product_id = pa.product_id) WHERE pa.options_values_id = 134
I think that you're asking how to get the product ID of anything have an attribute of 134
In that case, no JOIN is required.
SELECT DISTINCT
product_id
FROM
products_attributes
WHERE
options_values_id = 134
If you want the product_model then you could form the JOIN like this
SELECT DISTINCT
p.[product_model]
FROM
products p
JOIN
product_attributes pa
ON pa.[product_id] = p.[product_id]
WHERE
pa.[options_values_id] = 134
So the JOIN stipulates how the two tables are related to each other. Once there is a valid JOIN you can use the joined table nearly anywhere in the query.
You can try the following:
select p.product_id, p.product_model
from products p
inner join products_attributes pa on pa.product_id = p.product_id
where pa.options_values_id = '134'
I have got 2 tables: categories and products.
Categories have parent-child relationship structure and the data is fetched by joining the same table.
When fetching the data, I have to count:
how many products each category contains which have stock >= 1
how many subcategories a category contains which contain at least 1 product with stock >= 1
SELECT c. * , count( DISTINCT s.cat_id ) AS number_of_subcategories, count( DISTINCT p.id ) AS number_of_products FROM categories c
LEFT JOIN categories s
ON s.parent_id = c.cat_id
LEFT JOIN products p
ON p.cat_id = c.cat_id AND p.stock >= 1
GROUP BY c.cat_name
ORDER BY number_of_products ASC
At the first glance all goes well, but unfortunately I get total number of all subcategories.
Do I miss one more join or what is my problem so far?
Here is the code: SQLFiddle
You could alter your query to use a subquery to get the number of subcategories similar to this:
SELECT c.cat_id,
c.parent_id,
c.cat_name,
count(sp.cat_id) AS number_of_subcategories,
count(DISTINCT p.id) AS number_of_products
FROM `categories` c
LEFT JOIN
(
select distinct s.cat_id, s.parent_id
from categories s
inner join products p
on s.cat_id = p.cat_id
where p.stock > 1
) sp
ON sp.parent_id = c.cat_id
LEFT JOIN products p
ON p.cat_id = c.cat_id
AND p.stock >= 1
GROUP BY c.cat_id, c.parent_id, c.cat_name;
See SQL Fiddle with Demo
Try changing AND for WHERE. Does it work?
Francisco
I'm trying to create a rating system, where the user can rate pictures/videos/audio etc. I have two tables at the moment
Table: products
Cols: product_id[PK] | name | category | type | link
This is the products table and contains information about the products. If you're confused by products, think of the "product" as the image/video/audio, I named it like this simply for allowing me to understand it easier. The second table is the ratings
Table: product_ratings
Cols: rating_id[PK] | rating | product_id | timestamp
This table stores information about the rating the user has given.
I want a page where it will display the highest rating (on average) for all "products". So far, I've looked through SA, and found the follow piece of code:
SELECT
p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
WHERE p.product_id = 1
This just returns the average rating for a specific product_id, How would I go about getting ALL the product_ids and their average rating, and how would I find the highest one via PHP?
I've tried:
WHERE p.product_id < 1 AND p.product_id < 30
But this just returns product_id of 2, with it's name and average_rating, which I don't understand.
Guidance/links to material are welcome
SELECT
p.product_id,
p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
GROUP BY p.product_id
ORDER BY rating_average DESC
LIMIT 1
Just try:
SELECT
p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
also this is meaningless expression:
WHERE p.product_id < 1 AND p.product_id < 30
because it is completely equivalent to
WHERE p.product_id < 1
and i doubt that you have ids below zero
Your query is close. Just remove the WHERE clause that filters everything.
SELECT p.product_id, p.name,
AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
ORDER BY rating_average DESC
This will return you the averages for each product, sorted with the highest average rating at the top of the resultset.