Sql 对查询中返回的所有行求和,并在每一行中使用它

Sql 对查询中返回的所有行求和,并在每一行中使用它,sql,oracle,Sql,Oracle,我有一个查询(Oracle),按年份显示每个客户的销售额: SELECT cmp.company_key , sum(CASE WHEN sd.date between TO_DATE('01-Jan-2010', 'dd-mm-yyyy') and TO_DATE('11-Jun-2010', 'dd-mm-yyyy') THEN sd.qty_ship * sd.unit_price END) AS year1sales , sum(CASE WHEN sd.date bet

我有一个查询(Oracle),按年份显示每个客户的销售额:

SELECT cmp.company_key
    , sum(CASE WHEN sd.date between TO_DATE('01-Jan-2010', 'dd-mm-yyyy') and TO_DATE('11-Jun-2010', 'dd-mm-yyyy') THEN sd.qty_ship * sd.unit_price END) AS year1sales
    , sum(CASE WHEN sd.date between TO_DATE('01-Jan-2011', 'dd-mm-yyyy') and TO_DATE('11-Jun-2011', 'dd-mm-yyyy') THEN sd.qty_ship * sd.unit_price END) AS year2sales
FROM sales_detail sd
INNER JOIN sales_header sh on sd.sales_header_key = sh.sales_header_key
INNER JOIN companies cmp on sh.company_key = cmp.company_key
GROUP BY cmp.company_key
查询将生成以下结果:

company_key | year1sales | year2sales
------------|------------|------------
       8687 |   21355.76 |   54326.45
         25 |    9375.41 |      12401
         34 |    6440.03 |   50349.27
        247 |   47355.93 |   77432.67
         83 |   15757.35 |   39999.12
但我还需要它返回一个值(“TBI”),显示该公司的销售额与所有其他销售额之和的比较百分比

因此,对于公司#8687而言,它将是
21355.76/西格玛(第一年销售)
,即
21355.76/100284.48=21.3%

因此,结果将是:

company_key | year1sales | year1 TBI | year2sales | year1 TBI
------------|------------|-----------|------------|----------
       8687 |   21355.76 |     21.30 |   54326.45 |     23.17
         25 |    9375.41 |      9.35 |      12401 |      5.29
         34 |    6440.03 |      6.42 |   50349.27 |     21.47
        247 |   47355.93 |     47.22 |   77432.67 |     33.02
         83 |   15757.35 |     15.71 |   39999.12 |     17.06
很明显,TBI柱的总和为100%


您将如何编写此查询?还有,像这样的问题的时间复杂度是多少?我认为这是O(n^2)的最佳情况。

您可以使用
求和
来获得总数:

select
  company_key,
  year1sales,
  year1sales / sum(year1sales) over() as year1tbi,
  year2sales,
  year2sales / sum(year2sales) over() as year2tbi
from
(
  SELECT cmp.company_key
      , sum(CASE WHEN sd.date between date '2010-01-01' and date '2010-06-11' THEN sd.qty_ship * sd.unit_price END) AS year1sales
      , sum(CASE WHEN sd.date between date '2011-01-01' and date '2011-06-11' THEN sd.qty_ship * sd.unit_price END) AS year2sales
  FROM sales_detail sd
  INNER JOIN sales_header sh on sd.sales_header_key = sh.sales_header_key
  INNER JOIN companies cmp on sh.company_key = cmp.company_key
  GROUP BY cmp.company_key
)
order by company_key;

至于复杂性:我无法回答这个问题。数据库管理系统必须运行结果,构建总数,然后计算每行的百分比。

关于复杂性:对。DBMS的策略似乎是,如果不小心(即,计算每一行的总数,然后更新每一行中的每一行…)的话,它可能会采取一种不好的方法。这应该会简化一点。@LukaszSzozda我认为你的答案更正确,所以如果你把它作为一个答案,我会做标记it@ryvantage不需要。请随意将您的查询改写为RATIO_to_报告作为练习:)@Lukasz Szozda:感谢您提到
RATIO_to_报告
函数。我不知道。是的,这稍微简化了表达式,但更重要的是,它处理的是被零除的问题,我在表达式中甚至没有考虑到这一点。因此,我的表达式必须是
year1sales/nullif(sum(year1sales)over(),0)
,这就变成了一个
ratio\u/u report(year1sales)over()