2012-01-27 12 views
4

複数の地理的な区域で構成されている組織のメンバーが数年間にわたって獲得した賞を含む表がある場合、各地区の最優秀賞を授与するmysqlクエリはどのようなものでしょうか?私は簡単にこのクエリですべての地区全体でトップ10賞の所得を得ることができます:mysql - 2つの制限が必要ですか?

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 

それはメンバーのための正確な数を持っていますが、地区ごとに1を示したので、いくつかの地区が複数回表示されていません。各地区が一回だけ現れるように、地区ごとのトップ入賞者を列挙するにはどうすればよいですか?

答えて

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 

を検討してください。基本的には、賞金のすべての項目(a)について、同じ地区のすべてのエントリー(b)をより多くの賞で見つけて、(b)がなければ返すだけです。つまり、チャンピオンです。

同じ受賞数を持つ同じ地区に複数のメンバーがいる場合、これを微妙に調整する必要があります...このクエリはすべての結合メンバーを返します。それをどう扱うかを決める必要があります。賞をもらっていない地区には注意してください...あなたのテーブルにも登場しません。

+0

問題は、 'Number'は' count(Award).. GROUP BY Membername、District) 'の派生列だということです。 –

+0

それは問題ですか? –

+0

ええ、「カウントアップ(メンバー名ごとにa.ward、変わっている)<カウント(各メンバー名、地区ごとにb.award)」( 'Number'は' Awards'の列ではありません表)。 –

2

地区ごとに「ランク」を適用して、ランクごとにグラブを1つだけ行う必要があります。参加場所の@LastDistrictは、デフォルトではゼロに設定されています。 ID。 districtがcharベースの場合、代わりにデータ型に合わせて= ""に変更できます。

何が起こっているのかを明確にする。 「AwardCounts」の事前照会は、賞金総額の多い地区およびメンバーごとの全照会を行います。その後、地区および会員賞の数(降順)によって発注され、最高賞数が地区ごとに1位になります。

@RankSeqと@LastDistrictというクエリのインライン変数を作成する別の偽名 "SQLVars"に結合されています。だから、最初の "DistRankSeq"は最初の地区では1になり、 "@LastDistrict"には地区の価値がプライムされます。同じ地区の次のエントリー(適切な順番になるので)は、ランク2、そして3などに割り当てられます。「最後の」地区が新しいレコードになったときに変更があったときランクは1に戻って再び開始されます。だから、あなたは100人のメンバーを持つ地区、5人のメンバー、17人のメンバーを持つことができます。

最終的な質問にはそれぞれのランクがあります。 1 ...これを行うと、地区ごとに上位3人のメンバーを取得する必要性を調整することもできます(たとえば)...その集約thatsのは時間がかかっている場合、私は次のことを行うだろうFEEDBACK PER

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 

EDIT。地区の地区、名前、初期ランクごとの集計だけで新しいテーブルを作成します。新しいレコードがこのテーブルに追加されると、トリガーは集計テーブルのカウントに1を加え、その人が地区内のどこにいるかチェックし、新しいランクの位置を再更新します。それをさらに進めて、区域表ごとに「TOP」のメンバーを1つずつ、その人の名前とともに別のテーブルを作成することもできます。新しい人物がトップポジションに達すると、その名前がテーブルに置かれ、最後に誰かが上書きされます。

+0

私はそのクエリを実行し、5分後に完了していないので、動作しているのか、phpmyadminだけをハングしているのか分かりません。クエリは最終的にはインタラクティブなWebクエリのように使用されるため、長い完了時間は機能しません。表の使用には約400Kの行があります。 –

+0

@GeorgeMarshall、回答に追加のコメントを参照してください。 – DRapp

関連する問題