Assuming you want the "top" Product per category, you would need to group on category and use an aggregation (Max in this case).
Note, that even if mysql allows to have "unaggregated" columns along with an aggregation like bellow, the result might not be unique (MSSQL for instance does not allow such a query due to the missing aggregation/grouping on productName
):
SELECT
productName, -- unaggregated -> undetermined.
productCategoryID, -- grouping-condition -> fine
MAX((maxprice/minprice-1)*100) as PercentChange -- Aggregation -> fine
FROM products WHERE updatedDate > DATE_ADD(NOW(), INTERVAL -1 DAY)
AND productCategoryID NOT IN (0,58,12,13)
AND (maxprice/minprice-1)*100) < '60'
GROUP BY productCategoryID
ORDER BY PercentChange DESC LIMIT 10
Given the data is (simplified)
productName | productCategoryID | PercentChange
A 1 50
B 1 10
C 2 40
D 2 40
only the productCategoryID
and PercentChange
are reliable.
The result might be
A | 1 | 50
C | 2 | 40
but due to the lacking aggregation on productName
the following result might also be possible:
A | 1 | 50
D | 2 | 40
It WILL producte a single entry per category, but if two rows are equal with regards to their "grouping", the final result is not 100% predictable and therefore another approach should be taken.
You could - for example - group by name as well, and then programmatically filter out unwanted results:
SELECT
productName, -- grouping-condition -> fine
productCategoryID, -- grouping-condition -> fine
MAX((maxprice/minprice-1)*100) as PercentChange -- Aggregation -> fine
FROM products WHERE updatedDate > DATE_ADD(NOW(), INTERVAL -1 DAY)
AND productCategoryID NOT IN (0,58,12,13)
AND (maxprice/minprice-1)*100) < '60'
GROUP BY productName, productCategoryID
ORDER BY PercentChange DESC LIMIT 10
would result in
A | 1 | 50
C | 2 | 40
D | 2 | 40
Compared to a "non-grouped" query this would at least eliminate every entry that doesn't match MAX(PercentChange)
(per name and category).
ps.: If you want the minimum price change, use MIN()
obviously.