← Tüm yazılar

GROUP BY ile özet üretirken detayla tutarlılığı korumak

Özet rapor ile ayrıntı listesi farklı filtre kullanıyorsa iki doğru sorgudan yanlış bir ekran çıkar. Önce hangi kayıtların rapora dahil olduğunu belirleyip toplamı o küme üzerinden üretiyorum.

t.Turgay
GROUP BY ile özet üretirken detayla tutarlılığı korumak

Ayrıntı listesinde beş kayıt, üstteki özet kartında altı kayıt görünüyorsa kullanıcı önce hangi sayıya güveneceğini çözmek zorunda kalır. Çoğu zaman sorun SUM fonksiyonunda değil, iki sorgunun aynı veri kümesini kullanmamasındadır. Arşivimde arama, ayrıntı sayımı ve gruplu toplamları birlikte kullanan raporlarda önce “bu rapora hangi satırlar dahil?” sorusunu sabitlerim.

Özetin ölçü birimini tanımlamak

Örnekte üç satır var: A kategorisinde 10 ve 20, B kategorisinde 30. Kullanıcının filtresi Amount en az 20. Bu durumda A için bir satır ve 20 toplamı, B için bir satır ve 30 toplamı beklerim. Filtreli ayrıntının yanında A toplamını 30 göstermek istiyorsam bunun tüm veri toplamı olduğunu ayrıca adlandırmalıyım.

WITH Filtered AS (
  SELECT Category, Amount FROM (VALUES
    ('A',10),('A',20),('B',30)) AS d(Category,Amount)
  WHERE Amount >= 20
)
SELECT Category, COUNT(*) AS ItemCount, SUM(Amount) AS Total
FROM Filtered GROUP BY Category ORDER BY Category;

Bu VALUES tabanlı T-SQL örneği uygulama tablolarına dokunmadan denenebilir. Filtered ortak tablo ifadesi kabul edilen satırları adlandırıyor; GROUP BY ise o kümeden kategori başına bir satır çıkarıyor. COUNT(*) artık ilk tablonun değil, filtreden geçmiş satırların sayısıdır. CTE'nin görevi niyeti görünür kılmak; tek başına veriyi önbelleğe almak veya sorguyu hızlandırmak değildir.

WHERE ve HAVING farklı aşamalardır

WHERE Amount >= 20, gruplama öncesinde satırları eler. HAVING SUM(Amount) >= 20 ise grupların hesaplanan toplamına koşul koyar. A'nın 10 ve 20 değerlerini önce toplayıp 30'a göre grubu kabul etmek, 10 değerini baştan elemekle aynı sonuç değildir. Rapor şartını satır filtresi mi grup filtresi mi diye ifade etmek bu hatayı daha SQL yazmadan önler.

İlk iş olarak sorguyu çoğaltıp her ekrana ayrı filtre eklemek yerine filtre parametrelerini tek sorgu bileşeninden üretmeyi tercih ederim. CTE yalnız hemen arkasındaki SQL ifadesi için geçerlidir; sonraki bağımsız sorgu onun adını kullanamaz. Detay ve özeti ayrı komutlarla okuyacaksam ortak view, sorgu kurucusu veya işlem içindeki geçici veri kümesi gibi bir mekanizma seçmem gerekir.

Join satırları çoğaltıyorsa toplam da büyür

Bir başvuruyu üç belgeyle join etmek başvuruyu üç satıra çıkarabilir. Bu sonucun üstünde COUNT(*) çağırınca üç başvuru bulmuş olmam. Benzer şekilde ana kaydın tutarı her belge için tekrar toplanabilir. Önce raporun bir satırının neyi temsil ettiğini tanımlar, gerekiyorsa alt tabloyu kendi düzeyinde toplar veya EXISTS ile yalnız varlık kontrolü yaparım. DISTINCT her çoğalma sorununa otomatik çözüm değildir.

Null değerler de iş anlamı taşır. COUNT(*) satır sayarken COUNT(Amount) yalnız dolu tutarları sayar. SUM null tutarları hesaba katmaz; uygun girdi bulunmadığında sonucu sıfır saymak ise ayrı bir sunum ya da iş kararıdır. “Tutar bilinmiyor” ile “toplam sıfır” farklı şeylerse COALESCE'i düşünmeden eklemem.

Aynı filtre, farklı anlarda farklı sonuç verebilir

Detay ve özet arka arkaya ama ayrı okumalarla getiriliyorsa aradaki yeni kayıt fark yaratabilir. Bir rapor anının tutarlı olması gerekiyorsa veritabanının izolasyon seçeneklerini değerlendiririm. SQL Server'da snapshot seçeneklerinin etkinleştirilmesi gibi ortam gereklilikleri vardır; transaction açmanın her izolasyonda tüm okumaları aynı görüntüye sabitlediğini varsaymam.

Kontrolü küçük veriyle yapmak

Örneğin beklenen iki satırını önce elle hesaplamak mümkün: A/1/20, B/1/30. Sonra aynı veriye null tutar, hiç sonuç bırakmayan filtre ve çoğaltan join eklerim. Büyük tabloda performans için gerçek execution plan ve filtre/ilişki kolonlarının indeksleri incelenir. Bir CTE adı veya GROUP BY yazımı üzerinden ölçülmemiş hız iddiası üretmem.

T-SQL GROUP BY ve HAVING; CTE kapsamı ve çalışma biçimi.

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