Aggregate

計算一行佔總和的百分比

  • December 18, 2018

抱歉標題不好,我不確定什麼是好的標題。

這是我正在使用的目前(簡化視圖)數據

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

我需要計算佣金總額的百分比,每個代理負責。

因此,對於特工史密斯,百分比將計算為(Agent Smith's commission / Sum(commission)*100

所以,我的預期數據是

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

我有一個函式返回每個代理的佣金。我有另一個函式將百分比返回為(Commission/Sum(Commission))*100. 問題是要Sum(commission)為每一行計算,並且鑑於此查詢將在數據倉庫上執行,數據集會相當大(目前,它只有不到 2000 條記錄)而且老實說,這是一種糟糕的方法(IMO )。

有沒有一種方法可以Sum(Commission)不計算要獲取的每一行?

我在考慮兩部分查詢的內容,第一部分將獲取sum(commission)到包變數/類型中,第二部分將引用這個預先計算的值,但我不確定如何實現這一點。

我僅限於使用 SQL,並且我在 Oracle 10g R2 上執行。

您正在尋找analytical function ratio_to_report

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

要返回所有代理及其佣金和佣金百分比,請使用不帶分析子句的分析函式,以便分區覆蓋整個表:

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

正如我從 René Nyffenegger (+1) 那裡了解到的, ratio_to_report 函式收緊了這種語法。

使用包儲存佣金 SUM 將涉​​及 PL/SQL,您通過表明您需要 SQL 解決方案來明確排除它,但由於您已經在使用函式,我假設您的意圖不是排除 PL/SQL。如果是這種情況,那麼包解決方案可能會有所幫助,但這取決於您的應用程序的工作方式。

當您的會話首次創建並呼叫包中的函式以獲取佣金時,會隱式呼叫包建構子,該建構子可以獲取總和並將其儲存。然後你可以在你的獲取佣金函式中引用儲存的總和,它只需要計算一次總和。當然,一旦您從不同的會話中呼叫該函式,就會再次計算總和。此外,如果您的應用程序可以以這種方式設計,那麼為每個代理呼叫該函式的效率將大大低於為所有代理呼叫一條 SQL 語句的效率。

您可能需要考慮將您的函式轉換為為上述查詢返回游標的過程,或者可能有一個將查詢結果作為流水線結果集返回的函式。

樣本數據:

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);

引用自:https://dba.stackexchange.com/questions/653