Baris Top-N Per Grup dengan ROW_NUMBER
Pola partisi dan pemeringkatan standar untuk “3 teratas per kategori”.
Baris Top-N Per Grup dengan ROW_NUMBER adalah pelajaran Coding Interview Prep gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Coding Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Coding Interview Prep mencakup 4 pelajaran total.
Pertanyaan tentang N Teratas per Grup
Salah satu pertanyaan wawancara SQL yang paling umum terdengar sederhana: "Kembalikan 3 karyawan dengan gaji tertinggi di setiap departemen." Kandidat yang langsung menggunakan LIMIT akan gagal, karena LIMIT membatasi seluruh kumpulan hasil, bukan setiap grup.
Pewawancara sedang memeriksa apakah Anda memahami fungsi jendela. Jawaban bakunya adalah: beri nomor pada baris di dalam setiap grup, lalu pertahankan baris yang nomornya ≤ N. Pelajaran ini membangun pola tersebut langkah demi langkah.
Mengapa LIMIT Tidak Dapat Menyelesaikannya
Misalkan Anda menulis kueri di bawah ini. Kueri tersebut hanya mengembalikan 3 baris secara keseluruhan dari seluruh tabel, bukan 3 baris per departemen.
LIMIT (atau TOP, atau FETCH FIRST) bekerja pada kumpulan hasil akhir. Dalam SQL standar, tidak ada LIMIT per grup. Ketika pewawancara mendengar Anda mengusulkan LIMIT 3 untuk masalah per grup, itu menandakan bahwa Anda belum memahami pemartisian secara mendalam.
-- WRONG: only 3 rows total, not 3 per department
SELECT department, name, salary
FROM employees
ORDER BY salary DESC
LIMIT 3;Mengenal ROW_NUMBER
ROW_NUMBER() adalah fungsi jendela yang memberikan bilangan bulat unik tanpa celah kepada setiap baris sesuai urutan. Dengan sendirinya, fungsi ini memberi nomor pada seluruh hasil.
Bahan ajaibnya adalah PARTITION BY: fungsi ini mengulang penomoran dari 1 untuk setiap grup. Gabungkan PARTITION BY department dengan ORDER BY salary DESC, maka setiap departemen mendapatkan peringkatnya sendiri, 1, 2, 3, ... berdasarkan gaji.
SELECT
name,
department,
salary,
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS rn
FROM employees;Membaca Hasil yang Telah Diberi Nomor
Setelah menjalankan kueri sebelumnya, setiap baris memiliki nilai rn. Dalam setiap departemen, gaji tertinggi mendapatkan rn = 1, gaji berikutnya mendapatkan 2, dan seterusnya. Departemen baru mengatur ulang nilainya menjadi 1.
- Sales: Ana (1), Bo (2), Cal (3), Dee (4)
- Engineering: Eve (1), Fin (2), Gus (3)
Sekarang, "3 teratas per departemen" cukup berarti "pertahankan baris dengan rn <= 3".
Anda Tidak Dapat Menyaring rn di WHERE
Langkah berikutnya yang wajar adalah WHERE rn <= 3, tetapi langkah ini gagal. Fungsi jendela dihitung setelah klausa WHERE dalam urutan eksekusi logis, sehingga alias rn belum ada ketika WHERE dijalankan.
Pewawancara sangat suka menjadikan hal ini sebagai jebakan. Solusinya adalah menghitung fungsi jendela dalam subkueri atau CTE, lalu menyaring hasil kueri bagian dalam tersebut melalui kueri luar.
-- ERROR: rn does not exist in WHERE
SELECT name, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
FROM employees
WHERE rn <= 3;Solusi CTE Baku
Bungkus pemberian nomor dalam CTE bernama ranked, lalu pilih data darinya dengan penyaring di WHERE luar. Inilah jawaban yang ingin dilihat pewawancara, dan bentuknya juga mudah dibaca.
Hafalkan kerangka ini: partisi berdasarkan grup, urutkan berdasarkan metrik, lalu saring rn ≤ N dalam kueri luar. Pola ini berlaku untuk 1 teratas, 5 teratas, atau N berapa pun dengan mengubah satu angka.
WITH ranked AS (
SELECT
name, department, salary,
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS rn
FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE rn <= 3
ORDER BY department, rn;Bentuk Subkueri
Jika dialek yang digunakan pewawancara lebih lama atau mereka lebih menyukai subkueri, logika yang sama dapat ditempatkan dalam tabel turunan di FROM. Ingat, tabel turunan harus memiliki alias (r di sini), atau Anda akan mendapatkan kesalahan sintaks.
Bentuk CTE dan tabel turunan dapat dipertukarkan untuk masalah ini. Pilih bentuk yang menurut pewawancara lebih mudah dibaca; keduanya sama-sama benar.
SELECT name, department, salary
FROM (
SELECT name, department, salary,
ROW_NUMBER() OVER (
PARTITION BY department ORDER BY salary DESC
) AS rn
FROM employees
) AS r
WHERE rn <= 3;Satu Teratas: Yang Terbaik di Setiap Grup
"Temukan karyawan dengan gaji tertinggi di setiap departemen" hanyalah N = 1. Atur penyaring menjadi rn = 1.
Mengapa tidak menggunakan MAX(salary) dengan GROUP BY department? Karena MAX memberikan nilai gaji, tetapi tidak memberikan sisa baris karyawan tersebut, seperti nama, tanggal perekrutan, dan sebagainya. ROW_NUMBER mempertahankan seluruh baris pemenang, yang biasanya memang diinginkan oleh pertanyaan tersebut.
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY department ORDER BY salary DESC
) AS rn
FROM employees
)
SELECT name, department, salary, hire_date
FROM ranked
WHERE rn = 1;Menambahkan Penentu Seri yang Deterministik
ROW_NUMBER selalu mengembalikan tepat N baris, bahkan ketika terdapat beberapa gaji yang sama. Namun, baris dengan nilai sama mana yang mendapatkan rn = 1 bersifat sewenang-wenang jika seri tidak dipecahkan. Jika dua orang berpenghasilan 90000 dan Anda hanya mempertahankan rn = 1, baris yang terpilih dapat berbeda-beda antarpenggunaan.
Tambahkan kunci pengurutan sekunder yang unik, seperti employee_id, agar hasilnya stabil dan dapat direproduksi. Pewawancara menghargai kandidat yang menyebutkan determinisme tanpa perlu ditanya.
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC, employee_id ASC
) AS rnContoh Terapan
Diberikan tabel sales dengan region, product, dan revenue, kembalikan 2 produk teratas berdasarkan pendapatan per wilayah. Gunakan resep yang sama: partisi berdasarkan region, urutkan berdasarkan revenue DESC, lalu pertahankan rn <= 2.
Perhatikan bahwa hanya kolom partisi dan kolom metrik yang berubah. Strukturnya tetap sama, apa pun bidang bisnisnya.
WITH ranked AS (
SELECT region, product, revenue,
ROW_NUMBER() OVER (
PARTITION BY region ORDER BY revenue DESC, product
) AS rn
FROM sales
)
SELECT region, product, revenue
FROM ranked
WHERE rn <= 2
ORDER BY region, rn;Performa dan Poin Pembahasan
Untuk menunjukkan pemahaman yang lebih dari sekadar ketepatan, sebutkan hal-hal berikut:
- Indeks pada
(department, salary DESC)membantu mesin menghasilkan baris yang terurut per partisi secara efisien. - Pendekatan fungsi jendela memindai tabel satu kali, jauh lebih baik daripada subkueri berkorelasi yang dijalankan untuk setiap baris.
- Untuk kasus N teratas-1 yang sangat besar, beberapa mesin mendukung
DISTINCT ON(Postgres) sebagai jalan pintas, tetapiROW_NUMBERadalah standar yang portabel.
Selalu sebutkan penentu seri Anda dan pastikan N yang diminta.
Uji Cepat
Uji pemahaman Anda terhadap pola N-teratas-per-grup.
Ringkasan: N Teratas per Grup
Polanya secara singkat: partisi berdasarkan grup, urutkan berdasarkan metrik, tetapkan ROW_NUMBER, lalu pertahankan rn ≤ N dalam kueri luar.
LIMITmembatasi seluruh kumpulan, bukan per grup.- Anda tidak dapat menyaring alias fungsi jendela di
WHERE; bungkus dalam CTE atau subkueri. - Tambahkan penentu seri yang unik untuk mendapatkan hasil deterministik.
- Satu teratas mempertahankan seluruh baris pemenang, berbeda dari
MAX+GROUP BY.
Ubah satu angka, dan kueri yang sama dapat menyelesaikan kebutuhan satu teratas, lima teratas, atau N berapa pun.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Baris Top-N Per Grup dengan ROW_NUMBER” gratis?
Ya — teks lengkap “Baris Top-N Per Grup dengan ROW_NUMBER” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Coding Interview Prep, upgrade ke CoddyKit PRO. Kursus Coding Interview Prep mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Baris Top-N Per Grup dengan ROW_NUMBER”?
Pola partisi dan pemeringkatan standar untuk “3 teratas per kategori”. Kamu berlatih Coding Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Coding Interview Prep?
Tidak diperlukan pengalaman sebelumnya. Coding Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.
Berapa lama pelajaran “Baris Top-N Per Grup dengan ROW_NUMBER” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Coding Interview Prep ini?
Ya. Setiap pelajaran Coding Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Baris Top-N Per Grup dengan ROW_NUMBER
- Menangani Nilai Seri dalam Top-N
- Menghapus Duplikat Baris dengan Aman
- Mempertahankan Baris Terbaru Per Kunci