Bir satırın toplam toplam üzerinden yüzdesini hesaplama


13

Kötü başlık için özür dilerim, bunun için iyi bir başlık ne olacağından emin değildim.

Şu anda birlikte çalıştığım veriler (basitleştirilmiş görünümü)

Agent    |  Commission     
---------|------------
Smith    |    100
Neo      |    200
Morpheus |    300

Her komisyonun sorumlu olduğu toplam komisyonun yüzdesini hesaplamam gerekiyor.

Yani, Ajan Smith için Yüzde, (Agent Smith's commission / Sum(commission)*100

Beklediğim veriler

Agent    |  Commission   |  % Commission    
---------|---------------|---------------
Smith    |    100        |     17
Neo      |    200        |     33
Morpheus |    300        |     50

Her ajan için komisyonu iade eden bir fonksiyonum var. Yüzde olarak dönen başka bir işlevi var (Commission/Sum(Commission))*100. Sorun şu ki Sum(commission), her satır için hesaplanıyor ve bu sorgunun Veri Ambarı üzerinde çalıştırılacağı göz önüne alındığında, veri kümesi oldukça büyük (şu anda 2000 kayıtların biraz altında) ve dürüst olmak gerekirse, kötü bir yaklaşım (IMO) ).

Sum(Commission)Alınan her satır için hesaplamamanın bir yolu var mı ?

Ben 2 parçalı bir sorgu satırlarında bir şey düşünüyordum, ilk kısmı sum(commission)bir paket değişkeni / türü getirecek ve ikinci kısmı bu önceden hesaplanmış değere atıfta bulunacaktı, ama bunu nasıl başarabilirim emin değilim.

SQL kullanmakla sınırlıyım ve Oracle 10g R2 üzerinde çalışıyorum.


Açıkçası bir DBA sorusu değil (belki de satıcılar yerine tablo alanları olsaydı?) - muhtemelen Stack Overflow'da olmalıdır.
Gaius

Yanıtlar:


23

Aradığınız analytical function ratio_to_report

select 
  agent,
  round(ratio_to_report(commission) over ()*100) "% Comm."
from  
  commissions;

Harika, bunu bilmiyordum, teşekkürler!
Sathyajith Bhat18

9

Tüm aracıları komisyonları ve komisyon yüzdeleriyle döndürmek için , bölümün tüm tablonun üzerinde olması için analitik yan tümcesi olmayan bir analitik işlev kullanın :

SELECT Agent, commission, 100* commission / (SUM(commission) OVER ()) "% Commission" 
FROM commissions;

René Nyffenegger'den (+1) öğrendiğim gibi, oran_dönüştürme işlevi bu sözdizimini sıkılaştırır.

Komisyon SUM'u depolamak için bir paket kullanmak, bir SQL çözümü istediğinizi belirterek özellikle hariç tuttuğunuz PL / SQL'i içerecektir, ancak zaten işlevleri kullandığınızdan, niyetinizin PL / SQL'i dışlamak olmadığını varsayıyorum. Bu durumda, paket çözümü yardımcı olabilir, ancak uygulamanızın nasıl çalıştığına bağlıdır.

Oturumunuz ilk oluşturulduğunda ve komisyonu almak için paketteki işlevi çağırdığında, paket oluşturucusuna toplamı alıp saklayabilecek örtülü bir çağrı vardır. Sonra komisyon alma fonksiyonunuzda saklanan toplamı referans olabilir ve sadece bir kez yapmak gerekir. Elbette, işlevi farklı bir oturumdan çağırır çağırmaz toplam tekrar hesaplanır. Ayrıca, uygulamanız bu şekilde tasarlanabilirse, her aracı için işlevi çağırmak, tüm aracılar için bir SQL ifadesini çağırmaktan çok daha az verimli olacaktır.

İşlevinizi yukarıdaki sorgu için bir imleç döndüren bir yordama dönüştürmeyi veya sorgunun sonuçlarını ardışık düzenlenmiş bir sonuç kümesi olarak döndüren bir işleve sahip olmayı düşünebilirsiniz.

Örnek veri:

create table commissions (Agent Varchar2(100), Commission Number(3));
insert into commissions values ('Smith',100);
insert into commissions values ('Neo',200);
insert into commissions values ('Morpheus',300);

5

Aşağıdaki sorguyu deneyebilirsiniz, toplam (komisyon) yalnızca bir kez hesaplanacaktır:

WITH TOTAL_COMMISSION AS 
(SELECT SUM(COMMISSION) AS TOTAL FROM AGENTS)
SELECT A.AGENT_NAME, A.COMMISSION, ((A.COMMISSION/T.TOTAL)*100) AS "% COMMISSION"
FROM AGENTS A, TOTAL_COMMISSION T;

Bu çalışır ve doğru verileri döndürür, ancak iki yerine bir tam tablo taraması yapan (indeks olmadığı varsayılarak) analitik bir işlevden daha az verimlidir.
Leigh Riffel

1
@Leigh ~ Manüel yol iki geçiş gerektirdiğinden tek seferde nasıl yapabilir? Bilgisayarların% 'sini nasıl bir büyülü tek geçişli işlem
yapabileceğini göremiyorum

@jcolebrand Veriler sadece bir kez veritabanı bloklarından okunur. Muhtemelen bellek sonuçlarında birden fazla geçiş yapıyor, ancak bu genellikle veritabanı bloklarını iki kez okumaktan daha hızlıdır. Bu seçenekler arasında bellek ve CPU'da takaslar vardır, bu nedenle seçim her zaman net olmayabilir, ancak bu durumda olduğunu düşünüyorum.
Leigh Riffel

1
@Yüksek ~~ Evet, daha fazla dikkat edilmesi gereken her şeyin olabileceğine inanmamı sağlayacak , sadece kara kutu titiz optimizasyonları. Her neyse, cevabınızda şık bir çözüm. Teşekkürler: D
jcolebrand

0
  select 
  Agent, Commission,
  (
      ROUND(
       (Commission *100) / 
          (
            (SELECT SUM(Commission)
             FROM commissions AS A)
          )
       ) 
  ) AS Porcentaje
  from  
  commissions
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.