我有两个表客户端和分组。它们看起来像这样:
客户端
组合
客户端表包含每个客户端的每月利润,每个客户端属于C_grouping_id指定的特定分组方案。
分组表包含所有组及其每月利润。
我正在努力解决一个基本上计算每个订阅者每月剩余量的查询:
剩余=(订户每月利润 - 每月利润分组)*(所有月份的平均订户月利润/分组订户所有月份的平均利润属于)
到目前为止,我已经提出了以下查询,但结果似乎不正确:
SELECT client.C_id, client.C_grouping_Id, client.Month,
((client.Profit - grouping.profit) * (avg(client.Profit)/avg(grouping.profit))) as "residual"
FROM client
INNER JOIN grouping
ON "C_grouping_id"="Grouping_id"
group by client.C_id, client.C_grouping_Id,client.Month, grouping.profit
如果有人可以了解我做错了什么以及如何纠正错误,我将不胜感激。
编辑:添加样本数据和所需结果
客户
C_id C_grouping_id Month Profit
001 aaa jul 10$
001 aaa aug 12$
001 aaa sep 8$
016 abc jan 25$
016 abc feb 21$
分组
Grouping_id Month Profit
aaa Jul 30$
aaa aug 50$
aaa Sep 15$
abc Jan 21$
abc Feb 27$
查询结果:
C_ID C_grouping_id Month Residual
001 aaa Jul (10-30)*(10/31.3)=-6.38
......依此类推每个月的客户。
答案 0 :(得分:1)
这可以通过非常直接的方式完成。 显而易见的主要困难是您尝试同时处理不同级别的聚合(组和客户端的平均值以及当前记录)。
使用简单的SELECT FROM GROUP BY-SQL这是相当困难/笨拙的。 但是使用分析函数aka Window functions这很容易。
首先组合表并计算基数:
select c.c_id as client_id,
c.c_grouping_id as grouping_id,
c.month,
c.profit as client_profit,
g.profit as group_profit,
avg (c.profit) over (partition by c.c_id) as avg_client_profit,
avg (g.profit) over (partition by g.grouping_id) as avg_group_profit
from client c inner join grouping g
on c."C_GROUPING_ID"=g."GROUPING_ID"
and c. "MONTH" = g. "MONTH";
有了这个,您已经获得了客户和grouping_id的平均利润。 请注意,我将货币列的数据类型更改为DECIMAL(10,3),因为带有$符号的VARCHAR很难转换。 我还修复了MONTHS的数据,因为测试数据包含不同的大/小写拼写,这些拼写阻止了连接的工作。 最后,我将所有列名称都改为大写,以便更容易打字。
无论如何,运行它会为您提供以下结果集:
CLIENT_ID GROUPING_ID MONTH CLIENT_PROFIT GROUP_PROFIT AVG_CLIENT_PROFIT AVG_GROUP_PROFIT
16 abc JAN 25 21 23 24
16 abc FEB 21 27 23 24
1 aaa JUL 10 30 10 31.666
1 aaa AUG 12 50 10 31.666
1 aaa SEP 8 15 10 31.666
从这里开始,它只剩下剩余计算的一步。 您可以将此当前SQL放入视图中,以使其可以重用于其他查询,或将其用作内联视图。
我选择将它用作公共表格表达式(CTE)又名 WITH子句,因为它很好且易于理解:
with p as
(select c.c_id as client_id,
c.c_grouping_id as grouping_id,
c.month,
c.profit as client_profit,
g.profit as group_profit,
avg (c.profit) over (partition by c.c_id) as avg_client_profit,
avg (g.profit) over (partition by g.grouping_id) as avg_group_profit
from client c inner join grouping g
on c."C_GROUPING_ID"=g."GROUPING_ID"
and c. "MONTH" = g. "MONTH")
select client_id, grouping_id, month,
client_profit, group_profit,
avg_client_profit, avg_group_profit,
round( (client_profit - group_profit)
* (avg_client_profit/avg_group_profit), 2) as residual
from p
order by grouping_id, month, client_id;
请注意,整个陈述是多么容易阅读以及剩余计算是如何直接进行的。 结果就是:
CLIENT_ID GROUPING_ID MONTH CLIENT_PROFIT GROUP_PROFIT AVG_CLIENT_PROFIT AVG_GROUP_PROFIT RESIDUAL
1 aaa AUG 12 50 10 31.666 -12
1 aaa JUL 10 30 10 31.666 -6.32
1 aaa SEP 8 15 10 31.666 -2.21
16 abc FEB 21 27 23 24 -5.75
16 abc JAN 25 21 23 24 3.83
干杯, 拉斯