如何使用PL / SQL分析函数计算遗漏中位数

时间:2018-12-31 19:06:47

标签: sql oracle plsql

我正在尝试用PL / SQL编写一个解析函数,当将其应用于表中的列时,该函数将为表中的每一行返回,该列的中位数不包括给定行。

要澄清的示例:假设我有一个表TABLE,该表由一个具有以下值的列X组成:

1
2
3 
4 
5 

我想定义一个分析函数LOOM(),这样:

SELECT LOOM(X)
FROM TABLE

提供以下内容:

3.5
3.5
3
2.5
2.5 

,即,对于每行,X的中位数,不包括给定的行。我一直在努力构建所需的LOOM()函数。

1 个答案:

答案 0 :(得分:0)

我不确定是否有“聪明”的方法来做到这一点。您可以使用相关的子查询进行计算。

假设x的值是唯一的-如您的示例中所示-

with t as (
      select 1 as x from dual union all
      select 2 as x from dual union all
      select 3 as x from dual union all
      select 4 as x from dual union all
      select 5 as x from dual
     )
select t.*, 
       (select median(x)
        from t t2
        where t2.x <> t.x
       ) as loom
from t;

编辑:

更有效的方法使用解析函数,但需要更直接地计算中位数。例如:

with t as (
      select 1 as x from dual union all
      select 2 as x from dual union all
      select 3 as x from dual union all
      select 4 as x from dual union all
      select 5 as x from dual
     )
select t.*, 
       (case when mod(cnt, 2) = 0
             then (case when x <= candidate_1 then candidate_2 else candidate_1 end)
             else (case when x <= candidate_1 then (candidate_2 + candidate_3)/2 
                        when x = candidate_2 then (candidate_1 + candidate_3)/2
                        else (candidate_1 + candidate_2) / 2
                   end)
        end) as loom
from (select t.*,
             max(case when seqnum = floor(cnt / 2) then x end) over () as candidate_1,
             max(case when seqnum = floor(cnt / 2) + 1 then x end) over () as candidate_2,
             max(case when seqnum = floor(cnt / 2) + 2 then x end) over () as candidate_3
      from (select t.*,
                   row_number() over (order by x) as seqnum,
                   count(*) over () as cnt
            from t
           ) t
     ) t