2009-11-14 39 views
1

我有一个包含三个字段(item_id,source和price)的表。 (item_id,来源和价格)一起构成主键。聚合函数 - 获取不包含在GROUP BY子句中的列

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秒的时间才能创建,因此我希望找到替代方案。

回答

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中,临时表只对当前连接可见,并在连接关闭时自动删除。

+0

啊,我刚才提到你原来的解决方案会使运行时间加倍,我很高兴你提到临时表。也许临时表是在MySQL中执行此操作的最佳方式。我希望MySQL能够像Oracle一样使用WITH子句! – pcronin 2009-11-14 15:50:26

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

相关问题