计算一行占总和的百分比


13

不好意思,我很抱歉,对此我不确定。

这是我目前正在使用的数据(的简化视图)

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上运行。


显然,DBA问题(也许是表空间而不是销售人员?)可能应该在Stack Overflow上。
Gaius

Answers:



9

要返回具有佣金和佣金百分比的所有代理,请使用不带解析子句的解析函数,以使分区位于整个表中:

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

正如我从RenéNyffenegger(+1)中学到的,ratio_to_report函数加强了此语法。

使用一个包来存储佣金SUM会涉及PL / SQL,您通过指示您想要一个SQL解决方案特别排除了PL / SQL,但是由于您已经在使用函数,我假设您的意图是不排除PL / SQL。如果是这种情况,则打包解决方案可能会有所帮助,但这取决于您的应用程序的工作方式。

首次创建会话并调用包中的函数以获取佣金时,将对包构造函数进行隐式调用,该构造函数可获取和并存储和。然后,您可以在您的get Commission函数中引用存储的总和,而只需执行一次。当然,只要您从其他会话中调用该函数,就将再次计算总和。此外,如果可以采用这种方式设计应用程序,则为每个代理程序调用该函数的效率将比为所有代理程序调用一个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);

5

您可以尝试以下查询,sum(commission)仅计算一次:

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;

该方法可以工作并返回正确的数据,但效率比分析功能低,后者仅执行一次全表扫描而不是两次(假设没有索引)。
Leigh Riffel

1
@Leigh〜由于手动方式需要两次通过,如何才能一次完成?我看不到计算机如何使%ofTotal成为一次神奇的单

@jcolebrand数据仅从数据库块读取一次。它可能正在对其内存结果进行多次传递,但这通常比两次读取数据库块要快。这些选项之间在内存和CPU之间需要权衡取舍,因此选择不一定总是很明确,但在这种情况下,我认为是这样。
Leigh Riffel

1
@Leigh ~~是的,进一步的考虑会使我相信它可以做的只是黑匣子抖动优化。无论如何,这是一个很不错的解决方案。谢谢:D
jcolebrand

0
  select 
  Agent, Commission,
  (
      ROUND(
       (Commission *100) / 
          (
            (SELECT SUM(Commission)
             FROM commissions AS A)
          )
       ) 
  ) AS Porcentaje
  from  
  commissions
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.