← Tüm yazılar

ROW_NUMBER ile eşitlik bozma kurallı sıralama

Sıralamada eşit puanlar varsa yalnız Score DESC yeterli değildir. Aynı veri iki çalıştırmada farklı sırada görünüyorsa kullanıcı için sonuç güvenilir değildir.

t.Turgay
ROW_NUMBER ile eşitlik bozma kurallı sıralama

İki kaydın puanı eşitse hangisi önce gelecek? Bir sorgu ORDER BY Score DESC ile çalışabilir ama bu sorunun cevabını vermiş olmaz. Arşivimdeki sıralama sorgularında ROW_NUMBER kullanırken yalnız sıra numarası üretmeyi değil, o sıranın hangi iş kuralına göre belirlendiğini görünür tutmayı önemsiyorum.

Eşitlik bozma kuralını açıkça yazmak

Örnekte önce yüksek puan, sonra erken tarih, son olarak küçük Id öne geliyor. Tarihin öncelikli olması bu gösterim için seçilmiş bir kural; her değerlendirme sürecinin doğru kuralı olduğu iddia edilmiyor. Id ise kalan eşitliği teknik olarak kararlı hale getiriyor. Bu seçimin kullanıcıya anlatılabilir olması gerekir.

WITH Scores AS (
  SELECT * FROM (VALUES
    (1,'A',80,CAST('2026-01-02' AS date)),
    (2,'A',80,CAST('2026-01-01' AS date)),
    (3,'B',90,CAST('2026-01-01' AS date))
  ) d(Id,Team,Score,CreatedAt)
)
SELECT Id,
 ROW_NUMBER() OVER(ORDER BY Score DESC,CreatedAt,Id) AS OverallRank,
 ROW_NUMBER() OVER(PARTITION BY Team ORDER BY Score DESC,CreatedAt,Id) AS TeamRank
FROM Scores ORDER BY OverallRank;

Üç satırın genel sırası Id=3, Id=2 ve Id=1 olur. Id=3 puanı 90 olduğu için ilk; diğer ikisi 80 puanda eşit, fakat Id=2'nin tarihi daha erken. TeamRank içinde B'nin tek kaydı birinci, A grubundaki kayıtlar kendi aralarında birinci ve ikinci. OverallRank ile TeamRank farklı bölümlendirme kapsamlarını temsil ediyor.

PARTITION BY sonucu gruplamaz

PARTITION BY Team her takım için sıra sayacını yeniden başlatır; ayrıntı satırlarını tek satıra indirmez. GROUP BY ile farkı budur. Aynı sorguda genel sıra ve takım içi sıra hesaplayabilmemiz, satırın hem genel hem yerel bağlamını kaybetmeden göstermeyi sağlar.

Pencere içindeki ORDER BY hangi numaranın hesaplanacağını belirler. Sorgunun sonundaki ORDER BY ise sonuç satırlarının hangi sırada döneceğini belirler. Birini yazmış olmak ötekini otomatik olarak sağlamaz. Ekranın “sıra” sütununa göre görünmesi isteniyorsa dış sıralama da buna uygun olmalı.

ROW_NUMBER ile RANK aynı sözleşme değildir

ROW_NUMBER her satıra ayrı numara verir. Gerçek eşit puanların aynı dereceyi paylaşması gerekiyorsa RANK veya DENSE_RANK değerlendirilir. Ancak onların ORDER BY listesine de benzersiz Id eklersem eşitliği zaten bozmuş olurum. “Paylaşılan derece” ile “ekranda kararlı gösterim” iki ayrı sıralama ifadesi gerektirebilir.

Örneğin 90, 80, 80, 70 puanlarında yalnız puana göre RANK 1,2,2,4; DENSE_RANK 1,2,2,3 üretir. Boşluklu derece ile sıkı derece arasındaki fark bilinçli seçilmeli. Kullanıcı birincilik veya kontenjan hesabı yapacaksa bu ayrıntı yalnız görsel biçimlendirme değildir.

Filtreyi hangi aşamada uyguluyorum?

WHERE koşulu pencere hesabından önce uygulanır. Yalnız A takımını bırakıp genel sıra hesaplarsam “tüm kayıtlar içindeki sıra” yerine “A içindeki sıra” bulurum. Genel sırayı koruyarak sonra A'yı göstermek istiyorsam sıra hesabını bir alt sorguda tamamlar, dış sorguda filtrelerim. Yetki kapsamı ise farklıdır; kullanıcıya hesaplatılmaması gereken veriyi sıraya dahil etmek ayrıca değerlendirilmelidir.

Liste değiştiğinde sıra numarası da değişebilir. ROW_NUMBER kalıcı kayıt kimliği değildir ve istemcinin güncelleme anahtarı olarak kullanılmamalı. Sayfalama yapılıyorsa aynı benzersiz sıralama bütün sayfalarda korunur; eşzamanlı değişiklikler için snapshot veya sayfalama stratejisi ayrıca seçilir.

Küçük veriyle kuralı doğrulamak

Aynı puanlı kayıtları aynı tarihe getirip Id'nin son eşitliği nasıl bozduğunu denerim. Sonra bir takımı filtreler, genel ve takım sırasının anlamını karşılaştırırım. Büyük tabloda execution plan içindeki sıralama maliyeti ve uygun indeksler incelenir; bir window fonksiyonunun varlığı tek başına yavaş veya hızlı olduğu sonucunu vermez.

T-SQL ROW_NUMBER; RANK dereceleme davranışı.

✳ Bu yörüngenin sonuna geldin.
Diğer yazıları keşfet →
turgay.Biraz kod, biraz piksel, bolca merak.© 2026 · Dünya’dan sevgilerle ✳