問題:
GROUP BY
を使用してデータをグループ化しました 各グループの最初の行のみを表示したい。
例:
データベースには、exam_results
次の表のデータを使用:
first_name | last_name | 年 | 結果 |
---|---|---|---|
ジョン | クライン | 2020 | 40 |
エディス | 黒 | 2020 | 43 |
マーク | ジョンソン | 2019 | 32 |
ローラ | 夏 | 2020 | 35 |
ケイト | スミス | 2019 | 41 |
ジェイコブ | 黒 | 2019 | 44 |
トム | ベネット | 2020 | 38 |
エミリー | ケリー | 2020 | 43 |
毎年、最高のresult
を持つ生徒を見つけましょう 。グループで最高の成績を収めている生徒が2人いる場合は、そのうちの1人を任意に選択して表示します。
解決策:
WITH added_row_number AS ( SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results ) SELECT * FROM added_row_number WHERE row_number = 1;
結果は次のとおりです。
first_name | last_name | 年 | 結果 | row_number |
---|---|---|---|---|
Jacob | 黒 | 2019 | 44 | 1 |
エミリー | ケリー | 2020 | 43 | 1 |
ディスカッション:
まず、各グループ内の各行に番号を割り当てるCTEを作成する必要があります。これを行うには、ROW_NUMBER()
を使用できます 働き。 OVER()
で 、行を分割するグループを指定します(PARTITION BY
)および行に番号を割り当てる順序(ORDER BY
。
内部クエリの結果を見てください:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
first_name | last_name | 年 | 結果 | row_number |
---|---|---|---|---|
Jacob | 黒 | 2019 | 44 | 1 |
ケイト | スミス | 2019 | 41 | 2 |
マーク | ジョンソン | 2019 | 32 | 3 |
エミリー | ケリー | 2020 | 43 | 1 |
エディス | 黒 | 2020 | 43 | 2 |
ジョン | クライン | 2020 | 40 | 3 |
トム | ベネット | 2020 | 38 | 4 |
ローラ | 夏 | 2020 | 35 | 5 |
各グループ内の行番号(つまり、年)を割り当てます。各行には、result
の値に基づいた行番号があります 桁。 DESC
のため、行は降順で並べ替えられます ORDER BY result
の後のキーワード 。 result
の値が同じグループ内に複数の行がある場合でも 、行にはまだ異なる番号が付けられています。ここで、EdithBlackとEmilyKellyのresult
は同じです。 ただし、行番号は異なります。この動作を変更し、グループ内の同じ結果に同じ行番号を割り当てるには、RANK()
を使用します またはDENSE_RANK()
ROW_NUMBER()
の代わりに 。
外部クエリでは、CTE(added_row_number
)そしてWHERE
を使用します 各グループから表示する行を指定する条件。ここでは、最初の行を表示するため、条件はrow_number = 1
です。 。
たとえば、2番目の行を取得するようにソリューションを簡単に変更できることに注意してください。 各グループの。
WITH added_row_number AS ( SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results ) SELECT * FROM added_row_number WHERE row_number = 2;
結果は次のとおりです。
first_name | last_name | 年 | 結果 | row_number |
---|---|---|---|---|
ケイト | スミス | 2019 | 41 | 2 |
エディス | 黒 | 2020 | 43 | 2 |
一方、2番目に高い値の行を取得する場合 result
の 各グループ内で、DENSE_RANK()
を使用する必要があります 働き。 ROW_NUMBER()
関数は、グループ内の各行に連続した番号を作成します。その結果、同じ結果であるDENSE_RANK()
の行に異なる値が割り当てられます。 関数は、同じ結果の行に同じ番号を与えます。
WITH added_dense_rank AS ( SELECT *, DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank FROM exam_results ) SELECT * FROM added_dense_rank WHERE rank = 2;
first_name | last_name | 年 | 結果 | ランク |
---|---|---|---|---|
ケイト | スミス | 2019 | 41 | 2 |
ジョン | クライン | 2020 | 40 | 2 |
JohnKleinのresult (40)
の値が2番目に高いことがわかります。 John Kleinは実際にはグループの3人目ですが、最初の2人の生徒は同じresult
を持っています どちらもrank = 1
です 。