【问题标题】:Hard query with aggregation聚合硬查询
【发布时间】:2014-11-26 17:16:47
【问题描述】:

我正在使用 Oracle SQL,我需要有关硬查询的帮助。

我有两张桌子 (table_A):

GroupID (int)
ClientID (int)
Age (int)

(table_B):

GroupID (int)
Budget (int)

我的查询应该针对每组客户进行:

  • 计算组的平均年龄
  • 计算平均预算 每个客户的年龄与平均年龄一样(年龄可以更大或更小) 1)。例如:Average_Age - 1
  • Output value:(预算)/(平均预算)

例如: table_A:

GroupID | ClientID  | Age
    A   |   11      | 26
    A   |   22      | 27
    A   |   33      | 21
    B   |   44      | 22
    B   |   55      | 29
    B   |   66      | 25
    C   |   77      | 23
    C   |   88      | 22
    C   |   99      | 20
    D   |   111     | 24
    D   |   222     | 26
    D   |   333     | 25

table_B:

GroupID | Budget
   A    |  100
   B    |  200
   C    |  300
   D    |  400

表中的值都不是固定的。 A组产值计算示例:

  • A组平均年龄:(27+27+21) / 3 = 24.6
  • 年龄在 23-25 之间的 ClientID 分别为:66、77、111、333。他们的平均预算为: (200+300+400*2)/4 = 325
  • 输出值应为:100 / 325 = 0.307

输出表应该是

 GroupID    |  Output Value
    A       |     0.307
    B       |     ....
    C       |     ....
    D       |     ....

任何建议如何做到这一点?我已经尝试了很多方法。我感到很失落。

【问题讨论】:

  • None of the values in the tables are not fixed. - 那么,所有值都固定了吗? (为了清楚起见)
  • 对不起。所有这些都不是固定的(我在上面更改了它)。

标签: sql oracle average


【解决方案1】:
select Q1.GroupID, Q2.Budget/Q1.Budget_avg as Output_value from
(
select GroupID,ClientID,avg(budget) as Budget_avg from table_A A,table_B B
where A.GroupID =B.GroupID
group by GroupID,ClientID
) Q1,(select GroupID,Budget from table_B) Q2
where Q1.GroupID = Q2.GroupID

你可以试试这个,让我知道这是否适合你?

【讨论】:

    【解决方案2】:

    准备测试数据(修正了名称和类型的拼写错误):

    drop table table_a;
    
    create table table_a(
    GroupID  varchar2(10),
    ClientID int,
    Age      int
    );
    
    drop table table_b;
    
    create table table_b(
    GroupID varchar2(10),
    Budget  int
    );
    
    
    insert into table_a values('A',   11  , 26);
    insert into table_a values('A',   22  , 27);
    insert into table_a values('A',   33  , 21);
    insert into table_a values('B',   44  , 22);
    insert into table_a values('B',   55  , 29);
    insert into table_a values('B',   66  , 25);
    insert into table_a values('C',   77  , 23);
    insert into table_a values('C',   88  , 22);
    insert into table_a values('C',   99  , 20);
    insert into table_a values('D',   111 , 24);
    insert into table_a values('D',   222 , 26);
    insert into table_a values('D',   333 , 25);
    
    insert into table_b values('A',   100);
    insert into table_b values('B',   200);
    insert into table_b values('C',   300);
    insert into table_b values('D',   400);
    
    commit;
    

    查询本身:

    select a1.GroupId, a2.groupid, a2.clientid, b1.budget/avg(b2.budget) over(partition by a1.groupid) as avg_budget
     from (select GroupId, trunc(avg(age)) as avg_age
            from table_a
           group by GroupId
         ) a1
     inner join table_a a2
        on a2.age between a1.avg_age - 1 and a1.avg_age + 1
     inner join table_b b1
        on b1.groupid = a1.groupid    
     inner join table_b b2
        on b2.groupid = a2.groupid    
    order by a1.GroupId, a2.clientid
    ;            
    

    结果:

    GROUPID GROUPID_1   CLIENTID    AVG_BUDGET
    A   B   66  0.307692307692308
    A   C   77  0.307692307692308
    A   D   111 0.307692307692308
    A   D   333 0.307692307692308
    B   A   11  0.666666666666667
    B   B   66  0.666666666666667
    B   D   111 0.666666666666667
    B   D   222 0.666666666666667
    B   D   333 0.666666666666667
    C   A   33  1.33333333333333
    C   B   44  1.33333333333333
    C   C   88  1.33333333333333
    C   C   99  1.33333333333333
    D   A   11  1.33333333333333
    D   B   66  1.33333333333333
    D   D   111 1.33333333333333
    D   D   222 1.33333333333333
    D   D   333 1.33333333333333
    

    【讨论】:

    • 哇。非常感谢。这根本不是一个简单的查询。我不确定我是否完全理解了这个查询。我有几个问题: 1. 你为什么使用 trunc() 函数? 2. 为什么在内部连接中使用了两次表“table_b”? 3. 我需要在最终表中用另外两列扩展查询:除了第一步中的“A 组平均年龄”之外,我还需要“A 组最大年龄”和“A 组最小年龄”。我只需要在内部选择中添加两个新列,其中包含“trunc(max(age))”和“trunc(min(age))”以及另外两个?
    • 很遗憾,我无法使用您的查询。它运行了太多时间。每个表都有大约 20,000 条记录。最后的建议是在更大的表(大 10 倍)上运行此查询。有什么方法可以让查询运行得更快?
    • 1.您说:Average_Age - 1 24 时。 2. 得到你需要的东西。请仔细检查查询 - 具有不同的分组级别,因此它需要自我连接/我认为您可以根据需要将其替换为分析功能。它是由你决定。 3. 那是你已经更清楚你需要什么了。我给了你基本的想法,你可以将它应用到现实生活中。
    • 在性能方面尝试使用解析函数而不是自连接和分组依据。考虑添加索引。
    • 已添加索引。仍然工作太慢。此外,table_a 有 40k 条记录,table_b 有 20k 条记录。 table_a 中的不同记录数等于 table_b(两者具有相同的组)。但是,当使用“select count(*)”选择整个查询而不是从查询中选择选定的列时,它给了我超过 68m 的记录,我想这就是性能缓慢的原因。
    猜你喜欢
    • 2014-11-26
    • 2013-12-06
    • 2021-09-27
    • 2019-05-07
    • 2018-12-18
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多