ProgramlamaSQL analisti

Katmanlı filtreleme ile etkili bir agregasyonun pencere fonksiyonları ve gruplama kullanarak nasıl gerçekleştirileceği? Yaklaşımların farkları nelerdir ve geliştiricilerin sıkça yaptığı hatalar nelerdir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Katmanlar (örneğin, önce filtreleme yapıp, sonra gruplar bazında toplamları hesaplayıp, en son tüm veri kümesi üzerinden) ile etkili agregasyonlar inşa etmek için pencere fonksiyonları (OVER()) ve iç içe geçmiş GROUP BY kullanılır.

  • GROUP BY ile gruplama, yalnızca seçilen alanlar üzerinden agregasyon yapar; "yabancı" satırların etkisini dışlamak için yalnızca ön filtre (WHERE) ile yapılabilir.
  • Pencere fonksiyonları, belirli veri parçaları üzerinde agregat hesaplamaya olanak tanır ve sonuç kümesine filtreler uygulayabilir (örneğin, yalnızca aynı grubun satırları arasında).

Örnek: Her yöneticinin yalnızca 'ödenmiş' durumundaki siparişler arasında maksimum sipariş toplamını bulalım ve ardından tümü arasında mutlak maksimum olan yöneticinin adını gösterelim.

WITH PaidOrders AS ( SELECT ManagerID, SUM(OrderAmount) AS TotalPaid FROM Orders WHERE Status = 'paid' GROUP BY ManagerID ), WithMax AS ( SELECT *, MAX(TotalPaid) OVER() AS MaxTotalPaid FROM PaidOrders ) SELECT ManagerID, TotalPaid FROM WithMax WHERE TotalPaid = MaxTotalPaid;

Bu yaklaşım (CTE + pencere fonksiyonları), çok katmanlı filtreleme ve agregasyonu gerçekleştirmeye olanak tanır.

Kandırmaca sorusu.

Kandırmaca: "WHERE filtresinin gruplamadan (GROUP BY) önce çalıştırılması ile HAVING'in sonra uygulanmasının farkı nedir? Bu genellikle raporlarda ne gibi sorunlar yaratır?"

Cevap: WHERE, gruplamadan önce satırları atar, yani kesin bir giriş kümesi sağlar. HAVING, agregat gruplarını filtreler — bu nedenle mantıksal olarak uyumlu olmayan bir filtre olduğunda geçici olarak "gereksiz" satırları "bırakabilir". Filtrenin yanlış yeri, genellikle nihai agregatlarda hata veya yanlış rapor sonuçlarıyla sonuçlanır.

-- Sadece 'ödenmiş' durumundakileri WHERE ile topluyoruz SELECT ManagerID, SUM(OrderAmount) FROM Orders WHERE Status = 'paid' GROUP BY ManagerID; -- Ya da hepsini topluyoruz, ardından HAVING ile kesiyoruz SELECT ManagerID, SUM(OrderAmount) FROM Orders GROUP BY ManagerID HAVING SUM(OrderAmount) > 1000;

Konunun ince ayrıntılarını bilmemekten kaynaklı gerçek hata örnekleri.


Hikaye

Proje: Satış raporları, denetim.

Hata: Geliştirici, agregatların yanlış bir şekilde ödenmemiş siparişleri içerdiği için HAVING Status='paid' yerine WHERE kullandı, bu nedenle personelin yıllık KPI'ları hatalı hesaplandı.



Hikaye

Proje: Banka analitiği.

Hata: Karmaşık bir agregasyona PARTITION BY olmadan pencere fonksiyonu uygulamaya çalıştılar, bu nedenle agregatlar tüm tablo üzerinden hesaplandı. Departman bütçesi hatalı bir şekilde hesaplandı — bu nedenle manuel olarak geri alma işlemi yapmak zorunda kaldılar.



Hikaye

Proje: İnternet mağazası, sipariş istatistikleri.

Hata: Optimizasyonda iç içe geçmiş pencere fonksiyonlarını göz ardı ettiler — bu nedenle sunucu verileri çoklu işleme yaptı, sorgu, sadece iki katmanlı GROUP BY ile çalışmaktan 20 kat daha yavaş hale geldi.