在mysql中为每组选择n行

时间:2014-12-13 20:10:47

标签: mysql greatest-n-per-group

我已经阅读了这篇文章http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/,它解决了我遇到的问题,但是我不太了解解决方案。

这是表格(来自文章)。

+--------+------------+-------+
| type   | variety    | price |
+--------+------------+-------+
| apple  | gala       |  2.79 | 
| apple  | fuji       |  0.24 | 
| apple  | limbertwig |  2.87 | 
| orange | valencia   |  3.59 | 
| orange | navel      |  9.36 | 
| pear   | bradford   |  6.05 | 
| pear   | bartlett   |  2.14 | 
| cherry | bing       |  2.55 | 
| cherry | chelan     |  6.33 | 
+--------+------------+-------+

问题是根据每个组的价格属性选择2个最小的行(按类型)。本文提供的一个优雅的解决方案是:

select type, variety, price
from fruits
where price = (select min(price) from fruits as f where f.type = fruits.type)
   or price = (select min(price) from fruits as f where f.type = fruits.type
      and price > (select min(price) from fruits as f2 where f2.type = fruits.type));

我不明白像这样使用整个表的别名:

(select min(price) from fruits as f where f.type = fruits.type)

任何人都可以解释这个查询是如何运作的吗?

1 个答案:

答案 0 :(得分:2)

您有许多解决方案,其中一个是使用left join,您可以查看它

select t1.* from test t1
left join test t2
on t1.type = t2.type and t1.price > t2.price
group by t1.variety
having count(*) <=1
order by t1.type,t1.price

逻辑是使用相同的表进行左连接,其中类型相同且价格低于另一个,最后执行group by变量,然后使用count()必须显示每组所需的记录数。请注意,在mysql中,您可以自由地在上述查询中使用group by子句,这种方式可能会在其他RDBMS中失败。

现在您对alias感到困惑,在上面的示例中,表名为test,在查询中,伪名称为t1。此外,当您执行自联接时,您必须为同一个表提供唯一的别名。在上面的示例中,同一个表与自身连接,因此我们需要确保为表提供一些别名。