【问题标题】:when more than one condition satisfies, how to group them to calculate average当满足多个条件时,如何将它们分组以计算平均值
【发布时间】:2019-06-16 15:42:49
【问题描述】:

我正在使用 Oracle 数据库,想计算不同地区的平均产品价格。

例子:

prod,amt,price
X,100,1
X,180,2
X,250,3
Y,90,2
Y,170,3
Y,280,3

这里产品 X 在一个地区的售价为 100,在另一个地区售价为 180..等等。

现在,对于某些分析,它们被分组为重叠的不同范围,我需要根据范围计算价格的平均值

需要的输出是

prod,rang(Amt),mean(price),
X,[0-200],1.5,
X,[150-300],2.5,
Y,[0-200],2.5,
Y,[150-300],3,

请注意,范围有很多,为了清楚起见,我只给出了 2 个。

我尝试如下,但 case 匹配第一个条件,并且只为 [0-200] 的 X 提供一个值,我需要 2 条记录

select prod, amt, price, 
case 
when amt between 0 and 200 then amt
when amt between 150 and 300 then amt
end as rng
from tablea

如何在 case 语句中获取 2 条匹配记录?

【问题讨论】:

    标签: sql oracle aggregate-functions unpivot


    【解决方案1】:

    使用单个条件进行两个查询并将它们合并。这不是一个完美的解决方案,但会起作用。

    SELECT prod, '0-200' rang, AVG( price )
    FROM   table_name
    WHERE  amt BETWEEN 0 AND 200
    GROUP BY prod
    UNION ALL
    SELECT prod, '150-300' rang, AVG( price )
    FROM   table_name
    WHERE  amt BETWEEN 150 AND 300
    GROUP BY prod
    

    【讨论】:

    • @Richard 这是一个有效的解决方案。可以通过 SELECT prod, '0-200' rang, AVG( price ) FROM table_name WHERE price BETWEEN 0 AND 200 GROUP BY prod UNION ALL SELECT prod, '150-300' rang, AVG( price ) FROM table_name WHERE price BETWEEN 150 AND 300 GROUP BY prod 等代码示例对其进行改进。
    • @MT0 这是在没有代码的情况下审查的。那时它没有提供答案(但作为建议的方法,将是对该问题的有效评论)。
    【解决方案2】:

    您可以使用conditional aggregation,然后使用unpivot

       select prod_a as "Prod",
              prod as "Range of Amounts",
              value as "Mean Price"
         from  
                (
                with tablea(prod,amt,price) as
                (
                  select 'X',100,1 from dual union all
                  select 'X',180,2 from dual union all
                  select 'X',250,3 from dual union all
                  select 'Y',90, 2 from dual union all
                  select 'Y',170,3 from dual union all
                  select 'Y',280,3 from dual 
                )
                select prod as prod_a,  
                avg(case when amt between 0 and 200 then price end) as avg_0_200,
                avg(case when amt between 150 and 300 then price end) as avg_150_300
                from tablea a
                group by prod
                 ) b  
        unpivot(value for prod in(avg_0_200,avg_150_300))
        order by prod_a;
    
       Prod  Range of Amounts   Mean Price
       ----  ----------------    ----------
       X     AVG_0_200              1.5
       X     AVG_150_300            2.5
       Y     AVG_0_200              2.5
       Y     AVG_150_300            3
    

    Rextester Demo

    【讨论】:

    • 感谢 Barbaros .. 它有效.. 知道为什么 Zaynul 的回答中 .. 对于 X,150-300,输出是 2.5 而不是 3?
    • also.. 告诉我如何使用 SQL 为许多此类范围生成文本模式 avg(case when amt between 0 and 200 then price end) as avg_0_200,
    • @stack0114106 因为 prod 'X' 有两行 amt 值 180,250 在 150-300 范围内,价格分别为 2,3,平均值为 (2+3)/2 = 2.5.不幸的是,您还不能为枢轴或非枢轴结构动态生成此类模式。 xml pivot 可能出现这种情况。
    猜你喜欢
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    相关资源
    最近更新 更多