2017-02-11 3 views
1

MySQLは、私は、ユーザーが1つの試合に勝ったとmatch_idを含んでいるほとんどのポイントを引き戻すMYSQLスクリプトを書きたい...私はこのようになりますテーブルを持っている詳細

user_id, match_id, points_won 
1   14   10 
1   8   12 
1   12   80 
2   8   10 
3   14   20 
3   2   25 

をグループ化します結果で - 言い換えれば...私は私は何ができるmatch_idを必要としなかった場合はもちろん

user_id, match_id, max_points_won 
1   12   80 
2   8   10 
3   2   25 

...

select user_id, max(points_won) 
from table 
group by user_id 

しかし、 "select"と "group by"にmatch_idを追加すると、すべてのマッチの行があり、 "select"(そして "group by"ではない)にmatch_idを追加すると、 points_wonに正しく関係しません。

(ユーザーが複数の一致上の点の同じ量を獲得した場合など)には特に安全に感じることはありませんので、理想的には、私は以下のいずれかを行うにはしたくない...

SELECT t.user_id, max(t.points_won) max_points_won 
, (select t2.match_id 
    from table t2 
    where t2.user_id = t.user_id 
    and t2.points_won = max_points_won) as 'match_of_points_maximum' 
FROM table t 
GROUP BY t.user_id 

ていますこの問題のためのよりエレガントなオプションがありますか?派生テーブルとして

select user_id, max(points_won) 
from table 
group by user_id 

答えて

2

これはMySQLよりも難しいです。 1つの方法は、ハックのビットですが、ほとんどの状況で動作します。一緒に

select user_id, max(points_won), 
     substring_index(group_concat(match_id order by points_won desc), ',', 1) 
from table 
group by user_id; 

group_concat()を連結全てmatch_id S、下降ポイントによって順序付け:すなわち、group_concat()/substring_index()トリックです。その後substring_index()が最初のものをとります。

二つの重要な注意点:

  • 結果の式は関係なく、内部型の文字列の種類を持っています。
  • group_concat()は、長さ(デフォルトは1,024文字)の内部バッファを使用します。このデフォルトの長さは変更できます。
+0

ありがとうゴードン - 実際に私が望んでいたものです! – d3wannabe

1

は、クエリを使用することができます。元のテーブルにこれを参加するあなたが何をしたいあなたを取得:

select t1.user_id, t1.match_id, t2.max_points_won 
from table as t1 
join (
    select user_id, max(points_won) as max_points_won 
    from table 
    group by user_id 
) as t2 on t1.user_id = t2.user_id and t1.points_won = t2.max_points_won 
+0

おかげでGiorgos - これは完璧に良い解決策ですが、私は(多分不必要)(同一の最大のポイントに複数のレコードがあるかどう例)最大値からpoints_wonに戻って参加について神経質だ – d3wannabe

0

EDIT:だけのPostgreSQL、SQLサーバ、Oracleの

あなたはROW_NUMBER使用することができ

:について

SELECT USER_ID, MATCH_ID, POINTS_WON 
FROM 
(
    SELECT user_id, match_id, points_won, row_number() over (partition by user_id order by points_won desc) rn 
    from table 
) q 
where q.rn = 1 

を同様の機能は、ゴードン・リノフの答えを見てください。これはarticleです。

あなたの例では、ユーザーごとに結果セットを分割し、points_won descで注文して最高の勝利ポイントを最初に取得します。

+0

申し訳ありませんdevoh - しかし、私は取得します"あなたのMySQLサーバーのバージョンに対応するマニュアルをチェックしてください"これを実行すると、おそらく他のバージョンの有効な解決策ですが、もちろん – d3wannabe

+0

私の悪いです。私はmysqlがSql-Server、Oracle、Postgreのようなrow_number()をサポートしていないことを知らなかった。 – devoh

0

私は内側のクエリに制限1を追加してクエリを最適化できると思います。

SELECT t.user_id, max(t.points_won) max_points_won 
, (select t2.match_id 
    from table t2 
    where t2.user_id = t.user_id 
    and t2.points_won = max_points_won limit 1) as 'match_of_points_maximum' 
FROM table t 
GROUP BY t.user_id 
+0

ありがとうalgojava - 唯一の問題は、元のサンプルクエリに欠陥があると思われることです - これを実行するときに「参照 'max_points_won'がサポートされていません(グループ関数への参照)」エラーが発生します – d3wannabe

関連する問題