如何使用连接和分组执行多个表计算

时间:2016-02-01 12:22:52

标签: sql time-series hana

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

客户端

  • C_ID
  • C_grouping_id
  • 利润

组合

  • GROUPING_ID
  • 利润

客户端表包含每个客户端的每月利润,每个客户端属于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

......依此类推每个月的客户。

1 个答案:

答案 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    

干杯, 拉斯