2012-04-01 75 views
4

有沒有更好的方法從MySQL表中獲取多個「前X」結果?我能夠與工會輕鬆地完成這個當不同FOO的數量少:MySQL爲表中的每個人選擇前X個記錄

(SELECT foo,score FROM tablebar WHERE (foo = 'abc') ORDER BY score DESC LIMIT 10) 
UNION 
(SELECT foo,score FROM tablebar WHERE (foo = 'def') ORDER BY score DESC LIMIT 10) 

我能明顯不斷增加的工會和菸草工業的每個值。但是,當foo有500多個不同的值時,這是不實際的,我需要每個值的前X個。

+0

即使靠性能 – zerkms 2012-04-01 23:05:23

回答

9

這種查詢可以用「最大n組」的含義來表述,您希望每個「組」的前10個分數是'foo'的值。

我建議你看看this link,這個問題奇妙地處理這個問題,從一個有意義的方式開始執行你的查詢並逐步優化它。

set @num := 0, @foo := ''; 
select foo, score 
from (
    select foo, score, 
     @num := if(@foo = foo, @num + 1, 1) as row_number, 
     @foo := foo as dummy 
    from tablebar 
    where foo IN ('abc','def') 
    order by foo, score DESC  
) as x where x.row_number <= 10; 

如果你想跨越所有水平foo執行此(即想象做一個GROUP BY foo),則可以省略where foo in ...線。

基本上,內部查詢(SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC)從表中獲取fooscore,首先按foo排序,然後得分遞減。

@num := ...只是增加每一行,爲foo的每個新值重置爲1。也就是說,@num只是一個行號/等級(嘗試運行內部查詢來查看我的意思)。

外部查詢隨後選擇行,其中所述秩/行數小於或等於10。

注:

您與UNION原始查詢刪除重複,因此,如果頂部10分數foo='abc'都是100,那麼只有一行將被返回(因爲(foo,score)對被複制10次)。這一個將返回重複。

+0

仍然有一個解決方案,很好,非常感謝 - 我真的偶然發現了你在我的搜索鏈接的頁面,但快速瀏覽錯誤地認爲它只是爲了顯示單個最好的每組的一排。猜猜我應該仔細研究一下。 – Exupery 2012-04-02 00:07:00

相關問題