2009-05-26 64 views
1

我有不同的對象由不同的用戶計算一個特定動作的發生表:的MySQL:查詢與前n聚集

CREATE TABLE `Actions` (
    `object_id` int(10) unsigned NOT NULL, 
    `user_id` int(10) unsigned NOT NULL, 
    `actionTime` datetime 
); 

用戶每次執行此操作,將某行插入。我可以指望有多少行動是每個物體上進行,並通過「活動」 Order對象:

SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count; 

我怎麼能限制結果對於前n對象? LIMIT子句在聚合之前應用,因此導致錯誤的結果。該表可能是巨大的(數百萬行),我可能需要每分鐘計數數十次,所以我希望儘可能有效地做到這一點。

編輯:實際上,機器是正確的,而且我在LIMIT被應用的時間錯了。我的查詢返回了正確的結果,但將它呈現給我的圖形用戶界面讓我失望......這種問題使這個問題變得毫無意義。抱歉!

回答

2

其實...極限是最後應用,一個最終的HAVING子句後。所以它不應該給你不正確的結果。但是,由於LIMIT是最後一次應用的,它不會提供更快的查詢執行速度,因爲臨時表必須在切斷結果之前按照操作次序進行創建和排序。此外,請記得按降序排列:

SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count DESC 
LIMIT 10; 

您可以嘗試向object_id添加索引以進行優化。這樣,只需要掃描索引而不是Actions表。

0
SELECT * FROM (SELECT object_id, count(object_id) AS action_count 
     FROM `Actions` 
     GROUP BY object_id 
     ORDER BY action_count) LIMIT 10; 
1

如何:

SELECT * FROM 
(
SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count 
) 
LIMIT 15 

另外,如果你有什麼必須是動作的最小數量的一些措施,包括(如與前n位的有肯定超過1000),你可以通過添加HAVING子句提高效率:

SELECT * FROM 
(
SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
HAVING action_count > 1000 
ORDER BY action_count 
) 
LIMIT 15 
1

我知道這個線程是2歲,但stackflow仍然認爲它相關,所以這裏去我的$ 0.02。 ORDER BY子句在計算上非常昂貴,所以應該在大型表中避免它們。一個小竅門我使用(部分來自喬·塞科的SQL for Smarties一)是一樣的東西:

SELECT COUNT(*) AS counter, t0.object_id FROM (SELECT COUNT(*), actions.object_id FROM actions GROUP BY id) AS t0, (SELECT COUNT(*), actions.object_id FROM actions GROUP BY id) AS t1 WHERE t0.object_id < t1.object_id GROUP BY object_id HAVING counter < 15 

會給你不排序前15名編輯的對象。請注意,從v5開始,mysql只會將結果集緩存爲完全重複(含空白)的查詢,因此嵌套查詢不會被緩存。使用視圖可以解決這個問題。

是的,它是三個查詢而不是兩個,唯一的好處是不必對分組查詢進行排序,但如果您有很多組,則速度會更快。

備註:該查詢對於沒有排序的中位數函數非常方便