聚合函数 - 获取GROUP BY子句中未包含的列

时间:2009-11-14 15:06:47

标签: sql mysql group-by aggregate-functions

我有一个包含三个字段的表(item_id,source和price)。 (item_id,source和price)一起组成主键。

item_id    source      price
-------    -------     -----
1          paris       13
1          london      12
1          newyork     15
2          paris       22
2          london      15
2          newyork     14

对于每个item_id,我想知道最便宜的地方,以及我将在那个地方支付的价格。对于上面的例子,我想看到以下输出:

item_id    source     price
-------    -------    ---------
1          london     12
2          newyork    14

有没有一种简单的方法可以做到这一点而不提两次表名?我正在使用MySQL,所以我不能使用WITH子句。

我已经在另一个用户的问题(Group related records, but pick certain fields from only the first record)中查看了联接的双查询解决方案,但我真的想避免两次提到该表。问题是这个问题中的简单表实际上代表了我实际问题中的内联视图,每次使用需要大约5秒钟,所以我希望找到替代方案。

2 个答案:

答案 0 :(得分:3)

这是一种方法,使用内部联接来过滤价格最低的行:

select i.* 
from items i
inner join (
    select item_id, min(price) as minprice
    from items 
    group by item_id
) cheapest on i.price = cheapest.minprice
    and i.item_id = cheapest.item_id

如果有多个价格最低的来源,它们都会显示出来。

编辑:由于您的问题提到项目视图需要很长时间才能构建,您可以将结果存储在临时表中。

create temporary table temp_items 
as 
select item_id, source, price from YourView

然后在临时表上运行分组查询。在MySQL中,临时表仅对当前连接可见,并在连接关闭时自动删除。

答案 1 :(得分:0)

遗憾的是,我不知道MySQL数据和字符串转换。但是,如果你按照正确的语法对它进行一些按摩可能会让你大吃一惊:

SELECT
   item_id,
   source = Convert(varchar(30), Substring(packed, 5, 30)),
   price = Convert(int, Substring(packed, 1, 4))
FROM
   (
      SELECT
         item_id,
         Min(Convert(binary(4), price) + Convert(varbinary(30), source) AS packed
      FROM items
      GROUP BY item_id
   ) X

这肯定是一个黑客。绝对不应该在所有情况下都使用它。但是,当性能至关重要时,有时它是值得的。

有关详细信息,请参阅this thread