2009-11-14 73 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

相關問題