2010-07-26 113 views
3

這裏是你的一個益智遊戲:MySQL限制,組和AVG查詢

我在一個名爲'jobs'的MySQL表中保留了集羣計算的東西的統計信息。每個作業行都有一個執行作業的主機(不是唯一的),作業執行時間(以秒爲單位),以及作爲PK的唯一整數,因此我可以通過訂購PK來訂購完成的作業。

截至目前,使用average和group by,我可以找到每個主機在所有完成的作業上的平均執行時間,以秒爲單位。我不需要平均每個主機的所有執行時間,而是需要每個主機最後五個作業的平均時間。

有各種各樣的操作和組合的例子,以及有限制操作的大量例子,但是有沒有什麼方法可以將兩者結合在一個相當直接的MySQL查詢中?

編輯:在這我不清楚這件事的情況下,我要爲主機1的平均5個執行時間,平均5個執行時間主機2等

回答

2

我最初的反應是使用極限平均限制爲5個結果,這使我建議:

select a.host, avg(a.execution_time) from (select id, execution_time, host from jobs order by id desc limit 5) a group by a.host; 

但很顯然,這個每個主機限制平均到最近五組的工作,而不是最近的5個工作崗位。

似乎很難使用LIMIT來限制平均值,而不使用某種存儲過程。這導致我考慮使用mysql變量爲每個作業分配每個主機的完成順序或位置。

這是未經測試,但它說明的理論應該是一個很好的起點:

首先,我們應該根據其主機上的位置分配給每個工作:

select 
    host, 
    execution_time, 
    @current_pos := if (@current_host = host, @current_pos, 0) + 1 as position, 
    @current_host := host 
from 
    (select @current_host := null, @current_pos := 0) set_pos, 
    jobs 
order by 
    host, 
    id desc; 

確定位置後,只需選擇聚合功能,將結果限制在前5位:

select 
    jt.host, 
    avg(jt.execution_time) 
from 
    (
    select 
    host, 
    execution_time, 
    @current_pos := if (@current_host = host, @current_pos, 0) + 1 as position, 
    @current_host := host 
    from 
    (select @current_host := null, @current_pos := 0) set_pos, 
    jobs 
    order by 
    host, 
    id desc 
) jt 
where 
    jt.position <= 5 
group 
    by host; 

請讓我知道這是否適用於您,或者如果還有更多我沒有考慮過的問題。這是一個有趣的問題。

+0

一個小問題;你遇到了同樣的問題,嵌套查詢將只返回5個主機。 – Rob 2010-07-26 12:40:11

+0

是的,我發現問題比我最初想象的更復雜。我已經更新了我的解決方案,試圖解決這個問題。 – 2010-07-26 14:16:25

+0

不錯!完美適合我。 – Rob 2010-07-27 14:56:18

1

我要爲主機1的平均5個執行時間,併爲主機2的平均5個執行時間等

哦......在這種情況下,使用:

SELECT x.host, AVG(x.execution_time) 
    FROM (SELECT j.pk, 
       j.host, 
       j.execution_time, 
       CASE 
       WHEN @host != j.host THEN @rownum := 1 
       ELSE @rownum := @rownum + 1 
       END AS rank, 
       @host := j.host 
      FROM JOBS j 
      JOIN (SELECT @rownum := 0; @host := '') r 
     ORDER BY j.host, j.execution_time DESC) x 
WHERE x.rank <= 5 
GROUP BY x.host 

MySQL沒有任何排名/分析/窗口功能,但支持變量,因此您可以在ROW_NUMBER() OVER (PARTITION BY host ORDER BY execution_time DESC)獲得相同的功能。

此前:

 SELECT AVG(j.execution_time) AS avg_last_five_jobs 
     FROM JOBS j 
     JOIN (SELECT t.pk 
        FROM JOBS t 
      ORDER BY t.pk DESC 
        LIMIT 5) x ON x.pk = j.pk 
+0

我也沒有這樣的運氣。我只得到一個結果,這不是平均水平。 – Rob 2010-07-26 12:43:43

+0

@Rob:根據澄清更新 – 2010-07-26 17:43:05

+0

嗯......到目前爲止,我對上述解決方案有幾個問題,不過我可能會多玩一些。 – Rob 2010-07-27 14:55:14