問題:
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です 。