MySQL使用ORDER BY和GROUP BY一起

4

我有一个包含id、价格、类别等信息的产品表格。我想从每个类别中提取1个最近的产品(即在其自身类别中具有最高ID)。

这是代码,它可以从6个类别获取6个产品,但它们都是最老的(具有最小ID)。

    SELECT * from items WHERE item_category = '2' or item_category = '4' or 
item_category = '12' or item_category = '13' or item_category = '14' or 
item_category = '19' GROUP BY `item_category`  ORDER BY `item_id`  LIMIT 6

按ID排序是在返回的6个项目数组上执行的,而不是在原始表上执行。

我如何提取最新的项目呢?

我认为最好的查询方式是什么?

select *
from items
where item_category in ("2","4","12","13","14","19")
group by item_category
order by item_category DESC

为什么要使用GROUP BY - Artem Ilchenko
1
如果禁用了ONLY_FULL_GROUP_BY,MySQL扩展标准SQL使用GROUP BY的方式允许选择列表、HAVING条件或ORDER BY列表引用非聚合列,即使这些列在功能上不依赖于GROUP BY列。这会导致MySQL接受前面的查询。在这种情况下,服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的,这可能不是您想要的。此外,无法通过添加ORDER BY子句来影响从每个组中选择的值。 - P.Salmon
你可以只使用 SELECT item_category, MAX(item_Id) ... GROUP BY item_category 这样的语句。但是我很惊讶 MySQL 没有在你尝试按照所选列中的单个列进行分组时抛出错误,而是允许你强制仅按非聚合列分组。实际上,这样做是不被允许的。 - apokryfos
你也可以这样写:SELECT * FROM items WHERE id IN (SELECT MAX(item_id) /* 你原来的查询语句 */)。 - apokryfos
@davidethell @apokryfos 这个查询语句出现了错误,我不确定原始查询语句的哪一部分需要放在/* your original query*/中,以apokryfos的回答为准。 SELECT item_category, MAX(item_id) AS max_id, * FROM items WHERE item_category IN ("2","4","12","13","14","19") GROUP BY item_category ORDER BY max_id - Denislav Karagiozov
显示剩余3条评论
1个回答

5

首先需要指出的是,如果您不打算将所有非聚合列包含在分组中,则应该训练自己不使用group by。例如:

SELECT col1,col2 FROM table GROUP BY col1 -- BAD
SELECT col1,col2 FROM table GROUP BY col1,col2 -- GOOD
SELECT col1,MAX(col2) FROM table GROUP BY col1 -- GOOD

这是因为在组内不唯一的列中,您会得到任意和不可预测的值,这是所有问题的根源。
话虽如此,您应该这样做:
SELECT item_category, MAX(item_id) 
FROM items 
WHERE item_category IN ('2','4','12','13','14','19') GROUP BY `item_category`

请注意,由于您只能拥有6个组,并且排序不再起作用,因此无需限制。
如果您想获取相应的项目行,请执行以下操作:
SELECT * 
FROM items 
WHERE item_id IN ( 
     SELECT MAX(item_id) 
     FROM items 
     WHERE item_category IN ('2','4','12','13','14','19') 
     GROUP BY item_category
);

以下方法也可能有效:
SELECT * 
FROM items i JOIN (
       SELECT i2.item_category, MAX(i2.item_id) as max_item_id 
       FROM items i2
       WHERE i2.item_category IN ('2','4','12','13','14','19') GROUP BY 
       i2.`item_category`
) max_ids ON i.item_id=max_ids.max_item_id;

感谢您提供代码和时间!!对我来说最终的解决方案是在第一个SELECT中添加*,这将返回每个项目的每个列。SELECT *,item_category,MAX(item_id) FROM items WHERE item_category IN('2','4','12','13','14','19')GROUP BY item_category - Denislav Karagiozov
在执行此操作时,您需要非常小心。您不能确定作为“*”一部分返回的列与“MAX(item_id)”相对应。 - apokryfos
是的,它们不是...所以实际的最终查询是 - SELECT * from items WHERE item_id IN ( SELECT MAX(item_id) FROM items WHERE item_category IN ('2','4','12','13','14','19') GROUP BY item_category ) - Denislav Karagiozov
更新了答案以反映您实际所做的事情。不确定连接是否比选择/插入更好。我怀疑它们在性能方面差不多。 - apokryfos
这个操作非常简单,我认为差别可以忽略不计。尽管如此,还是做得很好! - Denislav Karagiozov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接