Raporlama amaçlı kullandığımız sistemler üzerinde en çok Ara Toplam (Sub Total) ve Alt Toplam (Grand Total) satırlarına ihtiyaç duyarız. Bunlarla birlikte özellikle karşılaştırmanın sözkonusu olduğu için verilerde özetlenmiş satırın tüm toplam içerisindeki payına yanı o satırın yüzdesine de (Percent To Total) ihtiyaç duyabiliriz. Bunun için SQL’de subquery yöntemi kullanılır veya SQL Server 2005 ile birlikte gelmiş olan OVER() fonksiyonu tercih edilir.
Aşağıdaki gibi Satış tablomuz olduğunu düşünelim.
Bu tabloyu Lokasyon’a göre özetleyip her lokasyon toplam grup içerisinde ciro payını yazdıralım.
Bunun için klasik yöntem olarak her satıra ait toplamı tüm toplama bölmektir.
SELECT s1.Lokasyon, SUM(s1.Tutar), SUM(s1.Tutar)*100/(SELECT SUM(s2.Tutar) FROM Satis s2) FROM Satis s1 GROUP BY s1.Lokasyon ORDER BY s1.Lokasyon DESC
Farklı bir yazım biçimi olarak sorguyu CROSS JOIN ile de yazabiliriz.
SELECT s1.Lokasyon, SUM(s1.Tutar), SUM(s1.Tutar)*100/MAX(s2.GrandTotal) FROM Satis s1 CROSS JOIN (SELECT SUM(Tutar) GrandTotal FROM Satis) s2 GROUP BY s1.Lokasyon ORDER BY s1.Lokasyon DESC
Tabloyu Lokasyon ve Ay bazında özetleyelim. Her lokasyon içerisindeki ayları alt toplama göre paylarını bulalım. Bu durumda paydaya gelecek olan toplam, tüm tablonun toplamı değil sadece o lokasyona ait toplam olacaktır.
SELECT s1.Lokasyon, s1.Ay, SUM(s1.Tutar) [Toplam Ciro], CAST( SUM(s1.Tutar)*100/(SELECT SUM(s2.Tutar) FROM Satis s2 WHERE Lokasyon=s1.Lokasyon) as numeric(4,2)) [Ara Toplam Ciro Payı(%)], CAST( SUM(s1.Tutar)*100/(SELECT SUM(s2.Tutar) FROM Satis s2) as numeric(4,2)) [Alt Toplam Ciro Payı(%)] FROM Satis s1 GROUP BY s1.Lokasyon, s1.Ay ORDER BY s1.Lokasyon, s1.Ay
Daha önceki makalelerde gördüğümüz WITH ROLLUP tümcesini de ekleyerek ara ve alt toplamları bulalım.
SELECT s1.Lokasyon, s1.Ay, SUM(s1.Tutar) [Toplam Ciro], CAST( SUM(s1.Tutar)*100/(SELECT SUM(s2.Tutar) FROM Satis s2 WHERE Lokasyon=s1.Lokasyon) as numeric(6,2)) [Ara Toplam Ciro Payı(%)], CAST( SUM(s1.Tutar)*100/(SELECT SUM(s2.Tutar) FROM Satis s2) as numeric(6,2)) [Alt Toplam Ciro Payı(%)] FROM Satis s1 GROUP BY s1.Lokasyon, s1.Ay WITH ROLLUP
Bu tür işlemlerde mevcut tabloyu birden fazla taradığımız hatta her satır için tarandığından sub-query kullanmak özellikle büyük tablolarda performans açısından kötü sonuç verecektir.
Şükür ki SQL Server 2005 ile birlikte sunulan OVER() fonksiyonu aracılığıyla aynı anda satırlara ait subtotal ve grand total satırlarını kolayca oluşturabiliyoruz. Örnek kullanımı aşağıda bulabilirsiniz.
SELECT Lokasyon, SUM(Tutar) OVER (PARTITION BY Lokasyon) AS 'Ara Toplam', SUM(Tutar) OVER () AS 'Alt Toplam' FROM Satis
Tablodaki her satır için ara ve alt toplam hesaplanmış oldu. Satırları tekilleştirmek için DISTINCT kullanabiliriz.
SELECT DISTINCT Lokasyon, SUM(Tutar) OVER (PARTITION BY Lokasyon) AS 'Ara Toplam', SUM(Tutar) OVER () AS 'Alt Toplam' FROM Satis
Ciro payını da ekleyelim
SELECT DISTINCT Lokasyon, SUM(Tutar) OVER (PARTITION BY Lokasyon) AS 'Ara Toplam', SUM(Tutar) OVER () AS 'Alt Toplam', SUM(Tutar) OVER (PARTITION BY Lokasyon)*100/SUM(Tutar) OVER () 'Ciro Payı(%)' FROM Satis
Daha anlaşılır olması açısından aşağıdaki gibi de yazabiliriz.
SELECT DISTINCT Lokasyon, [Ara Toplam]*100/[Alt Toplam] FROM ( SELECT Lokasyon, SUM(Tutar) OVER (PARTITION BY Lokasyon) AS 'Ara Toplam', SUM(Tutar) OVER () AS 'Alt Toplam' FROM Satis ) as T
SUM(Tutar) OVER () AS ‘Alt Toplam’ ifadesi tabloda seçilmiş kolonlara ait grand total’i hesaplar.
SUM(Tutar) OVER (PARTITION BY Lokasyon) AS ‘Ara Toplam’ ifadesi her lokasyon satırı için subtotal tutarını hesaplar.