Kurs
SQL’de veri kümelerinin sırasız olması yaygındır; bu da analizi zorlaştırabilir. Bir veri kümesindeki satırların birbirleriyle ilişkisini anlamak için ROW_NUMBER() işlevini kullanabiliriz.
Bu işlev, bir sonuç kümesindeki satırlara ardışık numaralar atayarak sonraki düzenleme ve analizler için net bir sıra sağlar. Bu, veri kümesinin tamamı için veya veri kümesi içindeki farklı veri grupları için yapılabilir.
Bu makale, SQL temelleri konusunda ön bilgiye sahip olduğunuzu varsayar. Yaygın olarak kullanılan ROW_NUMBER() işlevinin temellerini ele alacak ve zorluk seviyesi artan örnekler sunacağız.
ROW_NUMBER() Söz Dizimi
ROW_NUMBER() işlevinin temel söz dizimi şöyledir:
ROW_NUMBER() OVER([PARTITION BY value expression, ... ] [ORDER BY order_by_clause])
Temel bileşenleri parçalara ayıralım:
ROW_NUMBER(): Ardışık satır numaraları üreten işlevin kendisidir.OVER (...):ROW_NUMBER()gibi pencere işlevleri için zorunlu olan deyimdir. Satır numaralarının hangi bağlamda hesaplandığını tanımlar.PARTITION BY value_expression: Sonuç kümesini belirtilen sütun(lar) veya ifade(ler)e göre bölümlere ayıran isteğe bağlı deyimdir. Satır numaraları her bölüm içinde bağımsız olarak hesaplanır.ORDER BY order_by_clause: Satır numaralarının her bölüm içinde (veyaPARTITION BYkullanılmadıysa tüm sonuç kümesinde) hangi düzende atanacağını belirten isteğe bağlı deyimdir.
Örneklemek için, ROW_NUMBER() işlevini daha geniş bir SQL sorgusunda şöyle kullanabiliriz:
SELECT Val_1,
ROW_NUMBER() OVER(PARTITION BY group_1, ORDER BY number DESC) AS rn
FROM Data;
ROW_NUMBER() Örnekleri
Aşağıdaki üç örnekte ücretsiz DataLab IDE’sini kullanacağız. Employees örnek veri kümesini (DataLab’a zaten dâhil) kullanacağız; bu veri kümesinde şu dört sütun bulunur:
first_name: string alanılast_name: string alanıgender: iki değere sahip string alanı (“M” veya “F”)hire_date: çalışanın işe alındığı tarih
Veri kümesini aşağıdaki SQL kodunu kullanarak sorgulayabiliriz:
SELECT e.first_name, e.last_name, e.gender, e.hire_date
FROM employees.employees e
LIMIT 100; -- Optionally reduce the size of the output
Çalışanları alfabetik sırayla numaralandırma
ROW_NUMBER() kullanmadan önce amacımızı tanımlamak önemlidir—bu, bölümlendirip bölümlendirmeyeceğimizi ve nasıl sıralayacağımızı netleştirir. Bu örnekte tüm çalışanları alfabetik olarak sıralamak istiyoruz. Veri kümesindeki tüm çalışanları sıraladığımız için bir PARTITION BY deyimine gerek yok. Müşterileri soyadlarına (last_name) göre sıralayacağız. Numaralandırma sütunumuza name_row_number adını vereceğiz.
SELECT e.first_name, e.last_name, e.gender, e.hire_date,
ROW_NUMBER() OVER(ORDER BY e.last_name) AS name_row_number
FROM employees.employees e;

Eşitlikleri (aynı soyada sahip çalışanlar) yönetmek için sıralamayı daha fazla sütun ekleyerek hassaslaştırabiliriz. Aşağıdaki örnekte önce last_name ile sıralıyor, bir çalışanın soyadı başkasıyla aynıysa bu durumda adlarına (first_name) göre sıralıyoruz.
SELECT e.first_name, e.last_name, e.gender, e.hire_date,
ROW_NUMBER() OVER(ORDER BY e.last_name, e.first_name) AS name_row_number
FROM employees.employees e;

Çalışanları cinsiyet içinde en yeni işe alım tarihine göre numaralandırma
Şimdi, çalışanları kendi cinsiyetleri içinde en yeni işe alımdan en eskiye doğru sıralayalım. Yine ORDER BY deyimini kullanarak hire_date ile sıralayacağız, ancak bu kez en yeni işe alınanları önceliklendirmek için azalan düzende (DESC) kullanacağız.
Her cinsiyet için ayrı numaralandırma yapmak amacıyla PARTITION BY gender deyimini ekleyeceğiz. Bu, her bir farklı cinsiyet için satır numaralarının 1’den yeniden başlaması anlamına gelir.
Tam sorgu şu şekildedir:
SELECT e.first_name, e.last_name, e.gender, e.hire_date,
ROW_NUMBER() OVER(PARTITION BY gender ORDER BY hire_date DESC) AS hire_row_number
FROM employees.employees e;

Daha sonra her cinsiyette en deneyimli çalışanı bulmak için bu veriyi bir WHERE deyimi kullanarak sorgulayabiliriz:
WITH RankedEmployees AS (
SELECT e.first_name, e.last_name, e.gender, e.hire_date,
ROW_NUMBER() OVER(PARTITION BY gender ORDER BY hire_date DESC) AS hire_row_number
FROM employees.employees e
)
SELECT first_name, last_name, gender, hire_date
FROM RankedEmployees
WHERE hire_row_number = 1;

Bir JOIN kullanarak çalışanları cinsiyet içinde ücrete göre sıralama
Son örneğimizde, çalışanları cinsiyetlerini dikkate alarak ücretlerine göre sıralayacağız. Bunu başarmak için employees tablosunu emp_no sütununa göre salaries tablosuyla birleştireceğiz:
SELECT e.first_name, e.last_name, e.gender, e.hire_date, s.salary
FROM employees.employees e
JOIN employees.salaries s ON e.emp_no = s.emp_no
LIMIT 100;

Şimdi hem PARTITION BY hem de ORDER BY kullanacağız. Her cinsiyet için ayrı sıralamalar elde etmek üzere gender ile bölümleyecek, en yüksek kazananları önce sıralamak için de salary sütununu azalan düzende sıralayacağız.
Tam sorgu şu şekildedir:
SELECT e.first_name, e.last_name, e.gender, e.hire_date, s.salary,
ROW_NUMBER () OVER(PARTITION BY e.gender ORDER BY s.salary DESC) AS salary_row_number
FROM employees.employees e
JOIN employees.salaries s ON e.emp_no = s.emp_no
LIMIT 100;

Her cinsiyet için en yüksek ücretleri karşılaştırmak üzere sonuçları bir WHERE deyimiyle filtreleyebiliriz. Aşağıdaki sorgu, her cinsiyet için en yüksek gelirli ilk 5 kişiyi, kendi cinsiyet grubundaki sırasına göre döndürecektir. Bu tür sorgular, veri kümesi içinde ücret eşitliği hakkında içgörüler sağlayabilir.
WITH RankedSalaries AS (
SELECT e.first_name, e.last_name, e.gender, e.hire_date, s.salary,
ROW_NUMBER() OVER(PARTITION BY e.gender ORDER BY s.salary DESC) AS salary_row_number
FROM employees.employees e
JOIN employees.salaries s ON e.emp_no = s.emp_no
)
SELECT first_name, last_name, gender, hire_date, salary
FROM RankedSalaries
WHERE salary_row_number <= 5
ORDER BY salary_row_number, gender;

Sonuç
ROW_NUMBER() işlevi, sırasız bir veri kümesine sahip olduğumuzda ve satırlara sonraki analizler için net bir ardışık numaralandırma atamak istediğimizde kullanışlıdır. Bu numaraların belirli sırasını ORDER BY ile tanımlar, verideki farklı gruplar için ayrı numaralandırma dizilerini ise PARTITION BY ile belirleriz.
Bu makaleyi faydalı bulduysanız ve SQL hakkında daha fazla öğrenmek istiyorsanız diğer SQL kurslarımıza göz atın.
Veri Bilimi yazarı | Wayfair'da Kıdemli Teknik Pazarlama Analisti | University of Pennsylvania'da Veri Bilimi Yüksek Lisansı (MSE)
