質問

2つのテーブルがあります playersscores.

このようなレポートを生成したい:

player    first score             points
foo       2010-05-20              19
bar       2010-04-15              29
baz       2010-02-04              13

今、私の質問は次のように見えます:

select p.name        player,
       min(s.date)   first_score,
       s.points      points    
from  players p    
join  scores  s on  s.player_id = p.id    
group by p.name, s.points

必要です s.points それは行に関連付けられています min(s.date) 戻り値。それはこのクエリで起こっていますか?つまり、どうすれば私が正しいことを確信できますか s.points 参加した行の価値?

サイドノート:これは、MySQLの密集したランキングの欠如に何らかの形で関連していると思います。ここで最高の回避策は何ですか?

役に立ちましたか?

解決

これは、スタックオーバーフローで頻繁に出てくるグループごとの最大の問題です。

これが私のいつもの答えです:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and s2.date < s.date

where
  s2.player_id is null

;

言い換えれば、スコアSを与えられた場合、同じプレーヤーのスコアS2を見つけてみてください。以前のスコアが見つからない場合、Sは最も早いスコアです。


ネクタイについてのコメント:ネクタイの場合に使用するポリシーが必要です。 1つの可能性は、自動インクリメントプライマリキーを使用する場合、値が最小のプライマリキーは以前のキーです。以下の外側の結合の追加用語を参照してください。

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and (s2.date < s.date or s2.date = s.date and s2.id < s.id)

where
  s2.player_id is null

;

基本的に、少なくとも指定されたプレーヤーにとっては、ユニークであることが保証されている列に到達するまで、タイブレーカー用語を追加する必要があります。テーブルの主な鍵はしばしば最良の解決策ですが、別の列が適切な場合を見てきました。

@omg Poniesと共有したコメントに関しては、このタイプのクエリが適切なインデックスから大きなメリットをもたらすことを忘れないでください。

他のヒント

ほとんどのRDMBは、Group byを使用する際に選択句に非集約列を含めることさえできません。 MySQLでは、非凝集列のランダムな行からの値になります。これは、すべての行に対して特定の列に実際に同じ値を持っている場合に役立ちます。したがって、MySQLが私たちを制限しないのは素晴らしいことですが、理解することは重要なことです。

章全体がこれに捧げられています sql antipatterns.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top