2012-01-27 26 views
4

給出一個包含有由由多個地理區組織的成員贏得了在幾年獎項的表,什麼MySQL查詢將顯示在每個區的最高獎項收入來源?我可以很容易地在所有地區的前十名獲獎者與此查詢:mysql - 需要兩個限制?

SELECT Membername, count(Award)as Number FROM awards 
GROUP BY Membername 
ORDER BY Number desc 
LIMIT 10 

但我需要與頂級收入者名單各區(有其中約90),而我還沒有得到它是正確的。

我嘗試這樣做:

SELECT Membername, District, count(Award)as Number FROM awards 
GROUP BY Membername, District 
ORDER BY Number desc, District 
LIMIT 90 

它有一個成員準確計數,但沒有顯示每區之一,因此一些地區出現不止一次。我怎樣才能讓它列出每個地區的最高收入者,每個地區只出現一次?

回答

0

有做這一個相當普遍的方式,採用自聯接。訣竅是用'沒有更大的東西'來搜索'最大'搜索。正如你已經發現的

SELECT Membername, District, count(Award) as Number FROM awards 
GROUP BY Membername, District 

返回你一個很好的獎勵計數結果。讓我們寫...來節省一點空間作爲簡寫。

現在考慮

SELECT a.Membername, a.District, a.Number FROM (...) a LEFT JOIN (...) b 
ON a.District=b.District 
AND a.Number<b.Number 
WHERE b.Membername IS NULL 

其中...是東西上面寫的。它基本上是說,在頒獎計數的每個條目(一),發現我有更多的獎項同區的所有條目(B),並且只返回(一)如果沒有任何(B)的..換句話說,a是冠軍。

如果在同一個分區中有多個成員具有相同的獲勝次數,則需要稍微詳細一點......此查詢將返回所有綁定成員。你必須決定如何處理。並且注意那些根本沒有任何獎勵的地區......他們甚至不會出現在你的桌子上。

+0

問題是'Number'是一個派生列,是'count(Award).. GROUP BY Membername,District)''。 – 2012-01-27 03:15:03

+0

這是一個問題? – 2012-01-27 03:20:29

+0

是的,因爲'count'(每個成員名稱都是a.award,distrinct) 2012-01-27 03:28:26

2

您必須通過應用每個分區的「排名」來實現,然後只按每個排名抓取= 1 ...在連接位置的@LastDistrict默認爲零,以防該分區基於ID。如果分區是基於字符的,則可以將其更改爲=「」,而不是匹配數據類型。

爲了澄清所發生的事情。 「AwardCounts」預查詢可以爲每個地區和每個成員提供完整的查詢,無論是多少獎勵。然後,按地區和會員獎勵計數(降序)排序,從而將最高獎勵計數定爲每區第一位。

這是連接到另一個虛假別名「SQLVars」,它只是創建內聯變量到名爲@RankSeq和@LastDistrict的查詢。因此,第一次,「DistRankSeq」將成爲第一個地區的1,然後以該地區的價值填滿「@LastDistrict」。同一地區的下一個條目(因爲它將按照適當的順序排列)將被分配爲2,然後3等的等級......當從「最後」地區到新記錄存在變化時測試後,排名重新回到1並重新開始。所以,你可以有一個區100成員,另一個5,另一個17 ...

因此,您的最終查詢已全部與他們各自的隊伍......現在,應用HAVING最後的地區排名= 1 ...這樣做,你也可以調整必須得到每個地區前3名成員(例如)...

select 
     AwardCounts.District, 
     AwardCounts.MemberName, 
     AwardCounts.memberAwards, 
     @RankSeq := if(@LastDistrict = AwardCounts.District, @RankSeq +1, 1) DistRankSeq, 
     @LastDistrict := AwardCounts.District as ignoreIt 
    from 
     (select 
       a.district, 
       a.membername, 
       count(*) as memberAwards 
      from 
       Awards a 
      group by 
       a.district, 
       a.membername 
      order by 
       a.district, 
       memberAwards desc) AwardCounts 

     JOIN (select @RankSeq := 0, @LastDistrict = 0) SQLVars 
    HAVING 
     DistRankSeq = 1 

編輯每一次反饋 如果其聚集這就是抽空,然後我會做以下。創建一個新的表格,只包括每個區域的聚合,區域的名稱和初始等級。當任何新記錄被添加到該表中時,觸發器然後將一個新的記錄添加到聚合表計數中,然後檢查該人在他們的區域內的位置並且重新更新其新的等級位置。你可以更進一步,並在每個分區有另一張「TOP」會員表,每個分區有一個人的名字。當一個新人遇到最高職位時,他們的名字被放在桌子上,覆蓋最後一個人。

+0

我跑了那個查詢,五分鐘後,它沒有完成,所以我不知道它是否工作或只是掛了phpmyadmin。該查詢最終將用於交互式Web查詢中,因此很長的完成時間將不起作用。它使用的表格有大約400K行,順便說一句。 – 2012-01-27 05:24:56

+0

@GeorgeMarshall,請參閱答案中的其他評論。 – DRapp 2012-01-27 11:25:09