it-swarm.com.de

Berechnung des Prozentsatzes einer Zeile über der Gesamtsumme

Entschuldigung für den schlechten Titel, ich war mir nicht sicher, was ein guter Titel dafür sein würde.

Dies sind derzeit (vereinfachte Ansicht der) Daten, mit denen ich arbeite

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

Ich muss den Prozentsatz der gesamten Provision berechnen, für den jeder Agent verantwortlich ist.

Für Agent Smith würde der Prozentsatz also als (Agent Smith's commission / Sum(commission)*100 Berechnet.

Meine erwarteten Daten wären also

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

Ich habe eine Funktion, die die Provision für jeden Agenten zurückgibt. Ich habe eine andere Funktion, die den Prozentsatz als (Commission/Sum(Commission))*100 Zurückgibt. Das Problem ist, dass Sum(commission) für jede einzelne Zeile berechnet wird. Da diese Abfrage in einem Data Warehouse ausgeführt wird, ist der Datensatz ziemlich groß (derzeit sind es knapp 2000 Datensätze) und ziemlich groß Ehrlich gesagt, ein schlechter Ansatz (IMO).

Gibt es eine Möglichkeit, die Sum(Commission) nicht für jede abgerufene Zeile berechnen zu lassen?

Ich dachte etwas in den Zeilen einer zweiteiligen Abfrage, der erste Teil würde die sum(commission) in eine Paketvariable/einen Pakettyp holen und der zweite Teil würde auf diesen vorberechneten Wert verweisen, aber ich bin es nicht sicher, wie ich das erreichen kann.

Ich kann nur SQL verwenden und arbeite mit Oracle 10g R2.

13
Sathyajith Bhat

Du suchst das analytical functionratio_to_report

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

Um alle Agenten mit ihren Provisionen und Provisionsprozentsätzen zurückzugeben, verwenden Sie eine Analysefunktion ohne Analyseklausel, damit sich die Partition über die gesamte Tabelle erstreckt:

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

Wie ich von René Nyffenegger (+1) gelernt habe, verstärkt die Funktion ratio_to_report diese Syntax.

Die Verwendung eines Pakets zum Speichern der Provisionssumme würde PL/SQL beinhalten, das Sie ausdrücklich ausgeschlossen haben, indem Sie angegeben haben, dass Sie eine SQL-Lösung wünschen. Da Sie jedoch bereits Funktionen verwenden, gehe ich davon aus, dass Sie PL/SQL nicht ausschließen wollten. Wenn dies der Fall ist, kann die Paketlösung hilfreich sein, hängt jedoch davon ab, wie Ihre Anwendung funktioniert.

Wenn Ihre Sitzung zum ersten Mal erstellt wird und die Funktion im Paket aufruft, um die Provision zu erhalten, wird implizit der Paketkonstruktor aufgerufen, der die Summe abrufen und speichern kann. Dann könnten Sie auf die gespeicherte Summe in Ihrer Funktion zum Abrufen von Provisionen verweisen, und die Summe müsste nur einmal ausgeführt werden. Sobald Sie die Funktion aus einer anderen Sitzung aufrufen, wird die Summe natürlich erneut berechnet. Außerdem wäre das Aufrufen der Funktion für jeden Agenten erheblich weniger effizient als das Aufrufen einer SQL-Anweisung für alle Agenten, wenn Ihre Anwendung auf diese Weise entworfen werden kann.

Möglicherweise möchten Sie Ihre Funktion in eine Prozedur verwandeln, die einen Cursor für die obige Abfrage zurückgibt, oder eine Funktion haben, die die Ergebnisse der Abfrage als Pipeline-Ergebnismenge zurückgibt.

Beispieldaten:

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

Sie können die folgende Abfrage versuchen, Summe (Provision) wird nur einmal berechnet:

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