SQL ile Yüzde ve Oran Hesaplama: Pay, Grup İçi Pay, Hedef Gerçekleşme
Beceri rehberi

SQL ile Yüzde ve Oran Hesaplama: Pay, Grup İçi Pay, Hedef Gerçekleşme

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 6 dk okuma

SQL'de yüzde ve toplam içindeki payı SUM OVER ile hesaplamayı, tam sayı bölmesi tuzağını ve NULLIF ile sıfıra bölme hatasını önlemeyi örneklerle öğrenin.

Toplam içindeki pay nedir, SQL'de neden zor görünür?

Yüzde hesabı basit bir bölmedir: parça bölü bütün. Ancak SQL'de aynı sorgu satırında hem parçaya hem bütüne ihtiyaç duyulur. Bir ürünün satışı o satırdadır; tüm ürünlerin toplamı ise başka satırlardadır. Satır bazlı çalışan bir sorgu bu bütünü kendiliğinden göremez. Bu yüzden toplam içindeki payı hesaplamak, bütünü sorguya getirmenin bir yolunu gerektirir.

Başlıca yaklaşımlar şunlardır: pencere fonksiyonu ile toplamı her satıra taşımak, toplamı ayrı bir alt sorguda hesaplayıp birleştirmek ve toplamı CTE içinde hazırlayıp ana sorguda kullanmak. Pencere fonksiyonu yaklaşımı en kısa ve okunaklı olanıdır; diğerleri, pencere fonksiyonunu desteklemeyen sürümlerde ya da karmaşık raporlarda başvurulan alternatiflerdir.

Tipik sorular: her ürün toplam satışın yüzde kaçı, her bölgenin cirodaki payı, her müşteri segmentinin toplam içindeki oranı, hedefin ne kadarı gerçekleşti, dönüşüm oranı nedir. Hepsinde mantık aynıdır: payda doğru seçilmeli, sıfıra bölme engellenmeli ve tam sayı bölmesi tuzağından kaçınılmalıdır.

Pencere fonksiyonuyla pay hesabı

Toplamı her satıra taşımanın en pratik yolu, SUM fonksiyonunu boş bir OVER cümlesiyle çağırmaktır. OVER () tüm sonuç kümesini tek bir pencere yapar:

SELECT product, tutar, tutar * 100.0 / SUM(tutar) OVER () AS pay_yuzde FROM product_sales;

Burada SUM(tutar) OVER (), tablonun toplamını her satıra yazar; satırlar azalmaz. PostgreSQL belgesi pencere fonksiyonunun satırları bir araya getirmeden her satır için ilişkili satırlar üzerinden değer hesapladığını anlatır; pay hesabı bu özelliğin doğrudan uygulamasıdır.

Pay hesabını gruplar içinde yapmak için PARTITION BY eklenir. Örneğin her ürünün kendi bölgesinin toplamındaki payı:

tutar * 100.0 / SUM(tutar) OVER (PARTITION BY bolge) AS bolge_ici_pay

GROUP BY ile özetlenmiş veriden pay hesaplamak da yaygındır. Önce gruplayıp toplamı alırsınız, sonra bu toplamın toplamını pencere olarak kullanırsınız:

SELECT bolge, SUM(tutar) AS bolge_tutari, SUM(tutar) * 100.0 / SUM(SUM(tutar)) OVER () AS pay_yuzde FROM satislar GROUP BY bolge;

İçteki SUM bölge toplamını, dıştaki SUM(SUM()) OVER () ise bu bölge toplamlarının genel toplamını verir.

Tam sayı bölmesi tuzağı ve yuvarlama

En sık yapılan hata, tam sayıların bölümünün de tam sayı çıkmasıdır. PostgreSQL ve SQL Server'da tam sayı sütunları bölündüğünde sonuç ondalık kısım atılarak tam sayıya yuvarlanır; pay hesabında bu, pay değerlerinin sıfır görünmesine yol açar. Çözüm, bölmenin bir tarafını ondalık yapmaktır. Yukarıdaki örneklerde çarpanın ondalıklı yazılmasının nedeni budur. Alternatif olarak CAST ile ondalık tipe çevirebilirsiniz:

CAST(tutar AS DECIMAL) / SUM(tutar) OVER ()

MySQL'de bölme operatörü tam sayılarda bile ondalık sonuç verir; ancak başka bir ürüne taşıdığınızda davranış değişebileceği için ondalık çarpanı her durumda yazmak güvenli bir alışkanlıktır.

Sonucu raporlamak için yuvarlama kullanılır: ROUND(ifade, basamak). Yuvarlamanın yalnızca gösterim aşamasında yapılması önemlidir; ara hesaplarda yuvarlama, yüzdelerin toplamının tam bütüne eşit çıkmamasına neden olur. Gösterimde yuvarlanmış payların toplamı bütünden hafifçe sapabilir; bu doğal bir yuvarlama etkisidir ve raporda not edilmesi uygun olur.

Oran ile yüzde farkı da karıştırılmaz. Oran, bölümün ham sonucudur (ondalık kesir); yüzde ise bunun yüzde olarak ifade edilmiş halidir. Rapor aracı yüzde biçimini kendisi uyguluyorsa, sorguda ham oranı vermek ve çarpmamak gerekir; aksi halde değer katlanarak büyür.

Sıfıra bölme hatası ve boş değerler

Payda sıfır olduğunda sorgu hata verir. Tek bir ürünün satışı yoksa ya da filtre sonrası toplam sıfıra düşerse tüm sorgu çalışmaz. Klasik koruma NULLIF kullanmaktır: payda sıfıra eşitse NULLIF onu NULL yapar ve NULL'a bölme hata yerine NULL döndürür.

tutar * 100.0 / NULLIF(SUM(tutar) OVER (), 0) AS pay_yuzde

Sonuç NULL kalabilir; raporda sıfır görünmesi isteniyorsa ifadeyi COALESCE ile sarmalayın. Ancak NULL ile gerçek sıfır farklıdır: biri hesaplanamıyor, diğeri hesaplandı ve sıfır çıktı. Hangisinin raporda anlamlı olduğuna iş sorusu karar verir.

Paydadaki NULL değerler de dikkat ister. SUM, NULL satırları yok sayar; bu sıklıkla istenen davranıştır ama ortalama ya da sayım hesaplarında paydanın değişmesine yol açabilir. Pay hesaplamadan önce NULL'ların beklenen biçimde işlendiğini kontrol edin. NULL yönetiminin ayrıntısı için SQL NULL değerleri sayfası ilgilidir.

Farklı pay türleri: satır payı, sütun payı, toplam payı

Aynı veriden farklı payda seçimi farklı soruları cevaplar:

  • Genel toplam payı: payda tüm tablonun toplamı. "Bu ürün tüm satışın ne kadarı?" sorusu.
  • Grup içi pay: payda grubun toplamı. "Bu ürün kendi kategorisinin ne kadarı?" sorusu.
  • Önceki döneme göre değişim: payda önceki dönemin değeri. "Geçen aya göre artış yüzde kaç?" sorusu; bunun için önceki satırı getiren LAG fonksiyonu kullanılır.
  • Hedefe göre gerçekleşme: payda hedef değeri. "Hedefin yüzde kaçı gerçekleşti?" sorusu; hedef ayrı bir tablodan JOIN ile gelir.
  • Dönüşüm oranı: payda baştaki kitle. "Ziyaretçilerin ne kadarı sipariş verdi?" sorusu.

Her rapor için paydayı cümleyle yazmak, hata riskini azaltır: "Bu yüzde, X'in Y içindeki payıdır." Bu cümle yazılamıyorsa payda net değildir. Kümülatif payı biriktirerek göstermek için kümülatif toplam sayfasındaki kalıp kullanılır.

Koşullu pay da yaygındır: toplam içinde yalnızca belirli koşula uyan satırların payı. Bunun için payın içinde CASE kullanılır: SUM(CASE WHEN durum = 'iptal' THEN tutar END) ifadesi yalnızca iptal edilenleri toplar ve genel toplama bölünür.

Doğrulama ve sık yapılan hatalar

Pay hesabında en ucuz doğrulama, yüzdelerin toplamının bütüne yaklaşık eşit olup olmadığına bakmaktır. Bir grup içi paylar toplandığında ondalık farklar dışında bütün çıkmalıdır. Eşit çıkmıyorsa payda yanlıştır ya da filtre bütün ve parçayı farklı kümelerden almaktadır.

Sık yapılan hatalar:

  • Tam sayı bölmesi sonucu yüzdelerin sıfır görünmesi
  • Sıfıra bölme hatasını NULLIF ile engellememek
  • Filtre koşulunu parça ve bütün için farklı uygulamak: WHERE ile süzülmüş tablodan hesaplanan toplam, süzülmemiş bütünün payı değildir
  • Payda ile parçanın farklı granülaritede olması, örneğin günlük parça ile aylık bütün
  • Yüzdeyi tekrar tekrar çarpmak ya da çarpmayı unutmak
  • Yuvarlamayı ara adımda yapmak

Filtre konusu özellikle dikkat ister: WHERE koşulu pencere toplamından önce çalıştığı için toplam yalnızca süzülmüş satırlardan hesaplanır. Bütünün süzülmemiş toplam olması isteniyorsa toplam ayrı bir CTE'de hesaplanıp birleştirilir. Pay hesabı sonrası sıralama istenirse ROW_NUMBER ve RANK sayfası ile birleştirebilirsiniz.

Mindset programlarında bu beceri nerede çalışılır?

Toplam içindeki pay hesabı, rapor hazırlayan hemen herkesin kullandığı bir tekniktir: satış, finans, pazarlama ve operasyon raporlarında pay ve oran gerekir. Mindset'in SQL ile İleri Veri Dönüşümü ve Modelleme programı Pencere Fonksiyonları, Olgu Tabloları ve Toplulaştırma modüllerini içerir; SQL ile Veri Sorgulama (İleri) programında ise pencere fonksiyonları ile ileri analiz ve ileri vaka çalışmaları yer alır.

Programlar, SQL'in temelini bilen analist ve raporlama uzmanları için uygundur. Kurumsal ekiplerde pay ve oran raporlarını elle hazırlayan çalışanlar, kendi tablolarındaki sorular üzerinden çalışabilir. Kapsam ayrıntısı program sayfalarında yer alır.

İlgili Mindset programı

SQL ile İleri Veri Dönüşümü ve Modelleme

Sık sorulanlar

Sık sorulan sorular

SQL'de yüzde nasıl hesaplanır?

Parçayı bütüne bölüp yüzde için çarparsınız. Bütünü her satıra taşımak için SUM(tutar) OVER () kullanılır: tutar * 100.0 / SUM(tutar) OVER (). Ondalıklı çarpan, tam sayı bölmesinin sonucu sıfıra yuvarlamasını önler.

Yüzde hesabı neden sıfır çıkıyor?

Büyük olasılıkla tam sayı bölmesi yapılıyor. PostgreSQL ve SQL Server'da tam sayıların bölümü tam sayıdır ve küçük oranlar sıfıra yuvarlanır. Çarpanı ondalıklı yazmak ya da sütunu CAST ile DECIMAL tipine çevirmek sorunu çözer.

Sıfıra bölme hatasını nasıl engellerim?

Paydayı NULLIF ile sarın: NULLIF(payda, 0). Payda sıfırsa NULL döner ve NULL'a bölme hata vermez, sonuç NULL olur. Raporda sıfır göstermek istiyorsanız tüm ifadeyi COALESCE ile sarmalayın, ancak NULL ve sıfırın farklı anlamlar taşıdığını unutmayın.

Grup içindeki payı nasıl hesaplarım?

SUM fonksiyonunu OVER içinde PARTITION BY ile çağırın: tutar * 100.0 / SUM(tutar) OVER (PARTITION BY kategori). Payda artık tüm tablonun değil, satırın kategorisinin toplamıdır. Bu yüzden her kategori içinde paylar yaklaşık bütüne tamamlanır.

WHERE filtresi pay hesabını nasıl etkiler?

WHERE koşulu pencere toplamından önce çalışır, bu yüzden toplam yalnızca süzülmüş satırlardan hesaplanır. Yani süzülmüş kümede paylar bütüne tamamlanır, ama bütün sizin istediğiniz değilse yanıltır. Süzülmemiş toplam isteniyorsa toplamı ayrı bir CTE'de hesaplayıp birleştirin.

SQL'de Yüzde ve Toplam İçindeki Pay Hesaplama