2017-10-07 54 views
3

我得到了下面這個SQL-問題的幫助,總結了每個團隊的前5個長度。對我來說,現在的問題似乎是SQL隨機選擇了5個數據庫中的5個,例如數據庫中的25個,而不是前5個。任何人對我有什麼想法?會非常appriciated!SQL總結前5行爲每個團隊

select team, sum(length) as totalScore 
from 
(
    SELECT 
     t.*, 
     @num_in_group:=case when @team!=team then @num_in_group:=0 else @num_in_group:[email protected]_in_group+1 end as num_in_group, 
     @team:=team as t 
    FROM reg_catches t, (select @team:=-1, @num_in_group:=0) init 
    ORDER BY team asc 
) sub 
WHERE 
    sub.num_in_group <= 4 and 
    competition = 16 and 
    team = 25 
GROUP BY team 
ORDER BY totalScore DESC; 

team length competition 
---------------------- 
26 70  16 
25 70  16 
25 95  16 
25 98  16 
25 100  16 
25 100  16 
25 100  16 
25 122  16 

通緝輸出:

team totalScore 
---- ----------- 
25 520 
26 70 

最好的問候, 基督教

+0

表中沒有主鍵? –

+0

@PaulSpiegel爲什麼主鍵會在我們已經擁有的數據之上提供幫助? –

+0

@TimBiegeleisen你在自己的答案中寫道:「一些其他專欄打破領帶」。 –

回答

1

在你的內心查詢添加另一個排序子句

ORDER BY team asc ,length desc 

DEMO

這將順序表中排第一與團隊,然後爲每個團隊將訂單由長列值的行,球隊因此較高的值將返回第一

或者另一種方式來獲得您無需使用變量

select a.team, sum(a.length) as totalScore 
from (
select b.*,(
    select count(*) 
    from reg_catches c 
    where b.team = c.team 
    and b.length < c.length 
    ) + 1 rownum 
from reg_catches b 
) a 
where a.rownum <=5 
group by a.team 
order by totalScore DESC; 

DEMO

相同的結果

確保有團隊和長度列的索引,以獲得更好的性能

1

除此之外,您還必須與您當前所查詢的任何邏輯問題,有可能是在MySQL會話變量的行爲形式的其它風險。 MySQL並不保證在select語句中會話變量的分配順序。因此,用分區模擬排名(您的問題)的查詢可能不可靠。但是,我們仍然可以通過使用相關子查詢標記前5個長度爲每個團隊解決問題:

SELECT 
    team, 
    SUM(length) AS totalScore 
FROM 
(
    SELECT 
     team, 
     length, 
     competition, 
     (SELECT COUNT(*) FROM reg_catches t2 
     WHERE t2.team = t1.team AND t2.length >= t1.length) cnt 
    FROM reg_catches t1 
) t 
WHERE 
    cnt <= 5 AND 
    competition = 16 
GROUP BY 
    team 
ORDER BY 
    team; 

注意這個查詢有一個限制應該有存在的聯繫。如果你期待的是關係,那麼我們可以通過使用其他一列來打破這個關係。

輸出:

team totalScore 
1 25  520 
2 26  70 

演示在這裏:

Rextester

1

如果你想獲得前5排的每個team,你可以利用一個參數排名各球隊的結果:

SELECT *, 
(@rank := if(@team = team, @rank + 1, if(@team := team, 1, 1))) as rank 
FROM (SELECT * from reg_catches order by team, length desc) ordered 
HAVING rank <= 5 
ORDER BY team, rank asc 

這將產生如下:http://sqlfiddle.com/#!9/6042ae/1

| team | length | competition | rank | 
+------+--------+-------------+------+ 
| 25 | 99 |  16  | 1 | 
| 25 | 98 |  16  | 2 | 
| 25 | 77 |  16  | 3 | 
| 25 | 76 |  16  | 4 | 
| 25 | 73 |  16  | 5 | 
| 26 | 96 |  16  | 1 | 
| 26 | 88 |  16  | 2 | 
| 26 | 87 |  16  | 3 | 
| 26 | 83 |  16  | 4 | 
| 26 | 79 |  16  | 5 | 

然後,您可以,如果需要的話,換行查詢的簡單聚合/組得到總的前5位爲每個團隊

SELECT team, sum(length) as 'total score' FROM 
(SELECT *, 
(@rank := if(@team = team, @rank + 1, if(@team := team, 1, 1))) as rank 
FROM (SELECT * from reg_catches order by team, length desc) ordered 
HAVING rank <= 5 
ORDER BY team, rank asc) top5 
GROUP BY team 

作爲每http://sqlfiddle.com/#!9/6042ae/2

| team |total score| 
+-------+-----------+ 
| 25 | 423  | 
| 26 | 433  | 
| 27 | 426  | 

通常的警告將適用於參數,但是如果沒有它們,你無法在MySQL中真正「排名」。我還發現,在應用參數之前,最初以正確的順序獲得分數非常敏感。

雖然這可能不是最精緻的解決方案,但我希望它可以幫助