I have like this database tables:
Table categories
id title description status
Table products
id user_id category_id description status
Table product_varieties
id variety_id product_id description wholesale_price retail_price status total
I have query to get price min, max and avg in each category:
SELECT `categories`.`title`,
min(product_varieties.wholesale_price) AS wholesalePriceMin,
max(product_varieties.wholesale_price) AS wholesalePriceMax,
avg(product_varieties.wholesale_price) AS wholesalePriceAvg,
min(product_varieties.retail_price) AS retailPriceMin,
max(product_varieties.retail_price) AS retailPriceMax,
avg(product_varieties.retail_price) AS retailPriceAvg
FROM `products`
LEFT JOIN `categories`
ON `categories`.`id` = `products`.`category_id`
LEFT JOIN `product_varieties`
ON `product_varieties`.`product_id` = `products`.`id`
WHERE `products`.`id` IN (1,2,3,4)
GROUP BY `products`.`category_id`
Now I need get total users (sellers) of each category by editing my current query.
I tried like this:
SELECT `categories`.`title`,
min(product_varieties.wholesale_price) AS wholesalePriceMin,
max(product_varieties.wholesale_price) AS wholesalePriceMax,
avg(product_varieties.wholesale_price) AS wholesalePriceAvg,
min(product_varieties.retail_price) AS retailPriceMin,
max(product_varieties.retail_price) AS retailPriceMax,
avg(product_varieties.retail_price) AS retailPriceAvg,
(SELECT user_id,
COUNT(*)
FROM products
GROUP BY category_id) AS totalUsers
FROM `products`
LEFT JOIN `categories`
ON `categories`.`id` = `products`.`category_id`
LEFT JOIN `product_varieties`
ON `product_varieties`.`product_id` = `products`.`id`
WHERE `products`.`id` IN (1,2,3,4)
GROUP BY `products`.`category_id`
But my query not work and return error with message:
SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s)
How I can correct my query?
Advertisement
Answer
A “correlated subquery” can be used in the select list of your main query, this query must return just a single value and the “correlation” occurs through the where clause in that some data from the main query is used to locate the wanted data in the subquery.
SELECT
`categories`.`title`
, min(product_varieties.wholesale_price) AS wholesalePriceMin
, max(product_varieties.wholesale_price) AS wholesalePriceMax
, avg(product_varieties.wholesale_price) AS wholesalePriceAvg
, min(product_varieties.retail_price) AS retailPriceMin
, max(product_varieties.retail_price) AS retailPriceMax
, avg(product_varieties.retail_price) AS retailPriceAvg
, (
SELECT COUNT(*)
FROM products AS p
WHERE p.category_id = `products`.`category_id`
) AS totalUsers
FROM `products`
LEFT JOIN `categories` ON `categories`.`id` = `products`.`category_id`
LEFT JOIN `product_varieties` ON `product_varieties`.`product_id` = `products`.`id`
WHERE `products`.`id` IN (1, 2, 3, 4)
GROUP BY `products`.`category_id`
but I suspect this can be further simplified:
SELECT
`categories`.`title`
, min(product_varieties.wholesale_price) AS wholesalePriceMin
, max(product_varieties.wholesale_price) AS wholesalePriceMax
, avg(product_varieties.wholesale_price) AS wholesalePriceAvg
, min(product_varieties.retail_price) AS retailPriceMin
, max(product_varieties.retail_price) AS retailPriceMax
, avg(product_varieties.retail_price) AS retailPriceAvg
, COUNT(products.user_id) AS totalUsers
FROM `products`
LEFT JOIN `categories` ON `categories`.`id` = `products`.`category_id`
LEFT JOIN `product_varieties` ON `product_varieties`.`product_id` = `products`.`id`
WHERE `products`.`id` IN (1, 2, 3, 4)
GROUP BY `products`.`category_id`
or, depending on the data:
, COUNT(DISTINCT products.user_id) AS totalUsers