如何使用联接和分组依据执行多个 table 计算

How to perform multiple table calculation with joins and group by

我有两个 tables 客户端和分组。它们看起来像这样:

客户端

分组

客户 table 包含每个客户的每月利润,每个客户都属于 C_grouping_id 指定的特定分组方案。

分组 table 包含所有组及其每月利润。

我正在努力处理一个基本上计算每个订阅者每月剩余的查询:

残差=(订阅者月利润-分组月利润)*(订阅者所有月份的平均月利润/分组订阅者所属所有月份的平均利润)

到目前为止,我提出了以下查询,但结果似乎不正确:

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

...每个客户每个月以此类推。

这可以通过非常直接的方式完成。 主要困难显然是您尝试同时处理不同级别的聚合(组和客户端的平均值以及当前记录)。

这更像是 difficult/clumsy 和简单的 SELECT FROM GROUP BY-SQL。 但是使用分析函数 Window functions 这很容易。

开始组合 table 并计算基数:

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 的数据,因为测试数据包含不同的 upper/lower 大小写拼写,这会阻止连接工作。 最后我把所有的列名都变成了大写的to,为了打字更方便。

总之,运行 这为您提供了以下结果集:

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 放入视图中以使其可重复用于其他查询,或者将其用作内联视图。

我选择将它用作常见的 table 表达式 (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    

干杯, 拉斯