MySQLでOrder ByとGroup Byを同時に使う場合のSQL文


今回はMySQLでOrder ByとGroup Byを同時に使う方法を書きたいと思います。簡単なサンプルを交えて、失敗する事例と成功する事例を紹介していきます。

テーブルのサンプル

post-table-design

今回はpostというテーブルを作成し、id、title、author、createdという4つのフィールドを用意しました。ブログの記事を保存するためのテーブルという設定で話を進めたいと思います。

field-data

フィールドのデータを用意しました。記事ID、記事タイトル、投稿者、作成日というような構造になっています。

各投稿者の最新記事を1つずつ取得したい

投稿者毎の最新記事を1つずつ取得したい場合、Order ByとGroup Byを同時に利用したくなるのではないかと思います。

普通にSQLを書くと失敗する

SQLでOrder ByとGroup Byを同時に記述するとOrder Byが効かないという結果になります。

一度、上記のSQL文を実行してみようと思います。

query-result

一見、問題のないように見えますが、createdフィールドに注目してみてください。YOUKIの記事は、id2の行が最新のものになりますが、id1の方が表示されています。つまり、Group Byは動作していますが、Order Byが動作していない状態です。

なぜこのような事になるかと言うと、SQLには実行する順番があり、Group ByがOrder Byよりも先に実行される仕組みになっています。そして、その後にOrder Byが実行されるのですが、思っていた結果が返ってきません。なぜかと言うと、Group Byで重複している行を除外され、その後にOrder Byが実行されるからです。それならば、Order Byを実行してからGroup Byを実行すれば良いですね。

サブクエリを利用する事で解決できる

MySQLには、サブクエリという機能があります。まずは以下のSQL文を見てください。

このSQL文のFROMの後に括弧で括られている部分がサブクエリになります。このサブクエリの結果を元にメインのクエリが処理するという形になります。

つまり、サブクエリで先にOrder Byを呼び出しておき、そのソート済みの結果をメインクエリで更にGroup Byで絞り込むという事をしているわけです。

query-result2

上の画像が検索結果になります。各投稿者の最新記事が1件ずつ取得出来ていることが分かると思います。

ちなみに

という部分はサブクエリの結果に対して、独自の名前を付けています。なぜ名付けが必要かというと、メインクエリがこの結果をテーブルとして扱うからです。

説明は以上になります。Group ByとOrder Byの同時使用でハマってしまった方は試してみてください。

 


コメントを残す