我有一个SQL查询来选择以下情况下的金额总和。
有些经理负责许多地点的销售。所有地点的所有经理的销售金额都存储在同一表中。 我要从总表中选择“经理”名称,地点总数和他的总数。
以下是我所拥有的SQL。这是工作。但是考虑到表中有10万条记录,寻求一种更有效的实现方式。
SELECT
D1.Manager_name,
D1.location_name,
sum(D1.sale_amount) sale_amount,
(select sum(D2.sale_amount) from details D2 where D1.Manager_name = D2.Manager_name) total_amount
FROM details D1
GROUP BY
D1.Manager_name,
D1.location_name;
表格数据和预期输出数据
答案 0 :(得分:5)
您可以尝试使用SUM
作为窗口函数来替换相关的子查询:
SELECT
D1.Manager_name,
D1.location_name,
SUM(D1.sale_amount) sale_amount,
SUM(SUM(D1.sale_amount)) OVER (PARTITION BY D1.Manager_name) total_amount
FROM details D1
GROUP BY
D1.Manager_name,
D1.location_name;
这里是正在发生的事情的解释。窗口函数总是以 last 的形式求值。在窗口函数之后唯一执行的是ORDER BY
子句。在上述情况下,在GROUP BY
求值之后,中间结果中唯一可用的列是Manager_name
,location_name
和SUM(sale_amount)
。当我们将SUM
用作窗口函数时,按管理者划分分区,因此,我们可以找到所有聚集位置中每个管理者的总和。
答案 1 :(得分:1)
如果您接受另一种显示数据的方式,则可以使用GROUP BY子句的扩展名,该扩展名将一次性提供您想要的小计和总计。在这里,我生成99999行,并在0.03秒内得到输出。
with m(manager_name) as (
select 'Mgr '||level from dual connect by level <= 3
)
, l(location_name) as (
select 'Location '||level from dual connect by level <= 3
)
, s(sale_amount) as (
select level from dual connect by level <= 100000/9
)
select
Manager_name,
location_name,
sum(sale_amount) sale_amount
FROM m, l, s
GROUP BY Manager_name,
rollup(location_name);
MANAGER_NAME LOCATION_NAME SALE_AMOUNT
------------ ------------- -----------
Mgr 1 Location 1 61732716
Mgr 1 Location 2 61732716
Mgr 1 Location 3 61732716
Mgr 1 185198148
Mgr 2 Location 1 61732716
Mgr 2 Location 2 61732716
Mgr 2 Location 3 61732716
Mgr 2 185198148
Mgr 3 Location 1 61732716
Mgr 3 Location 2 61732716
Mgr 3 Location 3 61732716
Mgr 3 185198148