it-swarm.it

Calcolo della percentuale di una riga sulla somma totale

Mi scuso per il cattivo titolo, non ero sicuro di quale sarebbe stato un buon titolo per questo.

Attualmente sono (vista semplificata dei) dati con cui sto lavorando

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

Devo calcolare la percentuale della commissione totale, di cui ogni agente è responsabile.

Quindi, per l'agente Smith, la percentuale sarebbe calcolata come (Agent Smith's commission / Sum(commission)*100

Quindi, i miei dati previsti sarebbero

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

Ho una funzione che restituisce la commissione per ciascun agente. Ho un'altra funzione che restituisce la percentuale come (Commission/Sum(Commission))*100. Il problema è che Sum(commission) viene calcolato per ogni riga e dato che questa query verrebbe eseguita su un data warehouse, il set di dati sarebbe piuttosto grande (attualmente, è poco meno di 2000 record) e abbastanza onestamente, un cattivo approccio (IMO).

C'è un modo per far sì che Sum(Commission) non venga calcolato per ogni riga che viene recuperata?

Stavo pensando qualcosa sulle righe di una query in 2 parti, la prima parte avrebbe recuperato sum(commission) in una variabile/tipo di pacchetto e la seconda parte si sarebbe riferita a questo valore pre-calcolato, ma non lo sono sicuro come posso farlo.

Sono limitato all'utilizzo di SQL e utilizzo Oracle 10g R2.

13
Sathyajith Bhat

Stai cercando il analytical functionratio_to_report

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

Per restituire tutti gli agenti con le loro commissioni e percentuali di commissione utilizzare una funzione analitica senza clausola analitica in modo che la partizione si trovi su tutta la tabella:

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

Come ho appreso da René Nyffenegger (+1), la funzione ratio_to_report restringe questa sintassi.

L'uso di un pacchetto per archiviare il SUM della Commissione comporterebbe PL/SQL, che è stato specificamente escluso indicando che si desidera una soluzione SQL, ma poiché si stanno già utilizzando funzioni presumo che l'intenzione non fosse quella di escludere PL/SQL. In questo caso, la soluzione del pacchetto può essere d'aiuto, ma dipende da come funziona l'applicazione.

Quando la tua sessione viene creata per la prima volta e chiama la funzione nel pacchetto per ottenere la commissione, c'è una chiamata implicita al costruttore dei pacchetti che potrebbe ottenere la somma e memorizzarla. Quindi puoi fare riferimento alla somma memorizzata nella tua funzione get commission e dovrebbe fare la somma una sola volta. Naturalmente, non appena si chiama la funzione da una sessione diversa, la somma verrà nuovamente calcolata. Inoltre, la chiamata della funzione per ogni agente sarebbe notevolmente meno efficiente rispetto alla chiamata di un'istruzione SQL per tutti gli agenti se l'applicazione può essere progettata in quel modo.

È possibile considerare la possibilità di trasformare la propria funzione in una procedura che restituisce un cursore per la query sopra o magari avere una funzione che restituisce i risultati della query come set di risultati con pipeline.

Dati di esempio:

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);
9
Leigh Riffel

Puoi provare la seguente query, la somma (commissione) verrà calcolata una sola volta:

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;
5
Robert Durgin
  select 
  Agent, Commission,
  (
      ROUND(
       (Commission *100) / 
          (
            (SELECT SUM(Commission)
             FROM commissions AS A)
          )
       ) 
  ) AS Porcentaje
  from  
  commissions
0
JoeDeg