MySQLのテーブルから1列を結合します
-
30-09-2019 - |
質問
2つのテーブルがあります players
と scores
.
このようなレポートを生成したい:
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.