添加指标到顶部和底部10%

时间:2017-06-15 15:33:04

标签: oracle outliers case-statement

我正在尝试捕获FIRST_CONTACT_CAL_DAYS的平均值,但我想要做的是为最高和最低10%的值创建一个指标,这样我就可以从平均值计算中排除这些(异常值)。

不知道如何去做,有什么想法吗?

SELECT DISTINCT 
        TO_CHAR(A.FIRST_ASSGN_DT,'DAY') AS DAY_NUMBER,
        A.FIRST_ASSGN_DT,
        A.FIRST_CONTACT_DT,
        TO_CHAR(A.FIRST_CONTACT_DT,'DAY') AS DAY_NUMBER2,                   
        A.FIRST_CONTACT_DT AS FIRST_PHONE_CONTACT, 
        A.ID,
        ABS(TO_DATE(A.FIRST_CONTACT_DT, 'DD/MM/YYYY') - TO_DATE(A.FIRST_ASSGN_DT, 'DD/MM/YYYY')) AS FIRST_CONTACT_CAL_DAYS,   

        FROM HIST A
          LEFT JOIN  CONTACTS D ON A.ID = D.ID 

        WHERE 1=1

1 个答案:

答案 0 :(得分:1)

你可能正在寻找这样的东西。请适应您的情况。

我假设您可能有多个“组”或“分区”,并且在丢弃每个分区中的异常值后,您需要分别计算每个组的平均值。 (通过调整下面的查询可以很容易地适应的另一种方法是在全局范围内抛弃异常值,然后分组并取每个组的平均值。)

如果你没有任何群组,而且一切都是一大堆数据,那就更容易了 - 你不需要GROUP BY和PARTITION BY。

然后:函数NTILE根据它们落在哪里(第一个十分位数,即前10%,下一个十分位数,......一直到每行)为每一行分配一个桶号(在本例中为1到10之间)。最后一个十分位数)。我在子查询中这样做。然后在外部查询中,在分组之前过滤掉第一个和最后一个存储桶,然后计算平均值。

出于测试目的,我在WITH子句中创建了三个包含10,000个随机数的组 - 不需要花费任何时间在代码的那一部分上,因为它不是解决方案的一部分(解决问题的SQL代码) - 动态创建测试数据只是一个肮脏的技巧。

with
     inputs ( grp, val ) as (
       select     ceil(level/10000), dbms_random.value(0, 150)
       from       dual
       connect by level <= 30000
     )
select   grp, avg(val) as avg_val
from     (
           select grp, val, ntile(10) over (partition by grp order by val) as bkt
           from   inputs
         )
where    bkt between 2 and 9
group by grp
;

GRP                  AVG_VAL
---  -----------------------
  1 75.021614866547043734458
  2 74.286117923344418598032
  3 75.437412573353736953791