Masalah:
Anda telah mengelompokkan data Anda dengan GROUP BY
dan hanya ingin menampilkan baris pertama dari setiap grup.
Contoh:
Basis data kami memiliki tabel bernama exam_results
dengan data pada tabel berikut:
nama_depan | nama_belakang | tahun | hasil |
---|---|---|---|
John | Klein | 2020 | 40 |
Edit | Hitam | 2020 | 43 |
Tandai | Johnson | 2019 | 32 |
Laura | Musim panas | 2020 | 35 |
Kate | Smith | 2019 | 41 |
Yakub | Hitam | 2019 | 44 |
Tom | Bennett | 2020 | 38 |
Emily | Kelly | 2020 | 43 |
Untuk setiap tahun, mari temukan siswa dengan result
terbaik . Jika ada dua siswa yang mendapatkan nilai terbaik dalam satu kelompok, kami akan memilih salah satu dari mereka untuk ditampilkan.
Solusi:
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;
Hasilnya adalah:
nama_depan | nama_belakang | tahun | hasil | nomor_baris |
---|---|---|---|---|
Jacob | Hitam | 2019 | 44 | 1 |
Emily | Kelly | 2020 | 43 | 1 |
Diskusi:
Pertama, Anda perlu menulis CTE di mana Anda menetapkan nomor untuk setiap baris dalam setiap grup. Untuk melakukannya, Anda dapat menggunakan ROW_NUMBER()
fungsi. Dalam OVER()
, Anda menentukan grup di mana baris harus dibagi (PARTITION BY
) dan urutan nomor yang harus ditetapkan ke baris (ORDER BY
).
Lihatlah hasil dari inner query:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
nama_depan | nama_belakang | tahun | hasil | nomor_baris |
---|---|---|---|---|
Jacob | Hitam | 2019 | 44 | 1 |
Kate | Smith | 2019 | 41 | 2 |
Tandai | Johnson | 2019 | 32 | 3 |
Emily | Kelly | 2020 | 43 | 1 |
Edit | Hitam | 2020 | 43 | 2 |
John | Klein | 2020 | 40 | 3 |
Tom | Bennett | 2020 | 38 | 4 |
Laura | Musim panas | 2020 | 35 | 5 |
Anda menetapkan nomor baris dalam setiap grup (yaitu, tahun). Setiap baris memiliki nomor baris berdasarkan nilai result
kolom. Baris diurutkan dalam urutan menurun karena DESC
kata kunci setelah ORDER BY result
. Bahkan jika ada beberapa baris dalam grup yang memiliki nilai result
yang sama , baris masih diberi nomor yang berbeda. Di sini, Edith Black dan Emily Kelly memiliki result
yang sama tetapi nomor baris yang berbeda. Untuk mengubah perilaku ini dan menetapkan nomor baris yang sama untuk hasil yang sama dalam grup, gunakan RANK()
atau DENSE_RANK()
bukannya ROW_NUMBER()
.
Di kueri luar, Anda memilih semua data dari CTE (added_row_number
) dan gunakan WHERE
kondisi untuk menentukan baris mana yang akan ditampilkan dari setiap grup. Di sini, kita ingin menampilkan baris pertama, jadi kondisinya adalah row_number = 1
.
Perhatikan bahwa Anda dapat dengan mudah memodifikasi solusi untuk mendapatkan, misalnya, baris kedua setiap kelompok.
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;
Ini hasilnya:
nama_depan | nama_belakang | tahun | hasil | nomor_baris |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
Edit | Hitam | 2020 | 43 | 2 |
Sebaliknya, jika Anda ingin mendapatkan baris dengan nilai tertinggi kedua dari result
dalam setiap grup, Anda harus menggunakan DENSE_RANK()
fungsi. Sedangkan ROW_NUMBER()
fungsi membuat angka berurutan untuk setiap baris dalam grup, menghasilkan nilai berbeda yang ditetapkan ke baris dengan hasil yang sama, DENSE_RANK()
fungsi memberikan nomor yang sama ke baris dengan hasil yang sama.
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;
nama_depan | nama_belakang | tahun | hasil | peringkat |
---|---|---|---|---|
Kate | Smith | 2019 | 41 | 2 |
John | Klein | 2020 | 40 | 2 |
Anda dapat melihat bahwa John Klein memiliki nilai tertinggi kedua dari result (40)
untuk tahun 2020. John Klein sebenarnya adalah orang ketiga dalam grup, tetapi dua siswa pertama memiliki result
yang sama dan keduanya memiliki rank = 1
.