计算精度为99%的数据点

时间:2014-01-23 11:10:47

标签: sql oracle aggregate-functions precision percentile

我们有一张有数百万条记录的桌子。该表有两列,现在当X超出一个值时,X和Y之间存在相关性,Y趋向于B(但它并不总是如此,它的趋势不确定)。

这里我想找到X的阈值,即(X1),使得小于X1的值的至少99%为B.

可以轻松地使用代码完成。但是有一个SQL查询可以进行计算。

对于下面的数据集,预期为6,因为低于6,超过99%为'B',并且没有更大的X值,超过99%是'B'。但是,如果我将其更改为90%的精度,那么它将变为12,因为如果X <12,则超过90%的值为'B'并且没有更大的X值,它是真的

所以我们需要找到最大值X1,使得至少99%的值小于X1是'B'。

X   Y
------
2   B
3   B
3   B
4   B
5   B
5   B
5   B
6   G
7   B
7   B
7   B
8   B
8   B
8   B
12  G
12  G
12  G
12  G
12  G
12  G
12  G
12  G
13  G
13  G
13  B
13  G
13  G
13  G
13  G
13  G
14  B
14  G
14  G

3 个答案:

答案 0 :(得分:2)

好的,我认为这可以完成您想要做的事情,但适用于您提及的数据量。无论如何我都会张贴它,以防它可以帮助其他人提供答案。

这可能是其中一种最有效的方法是使用带有排序数据的游标。 Oracle有一些用于相关性分析的构建函数,但我从未使用它,因此我不知道它们是如何工作的。

select max(x)
  from (select x
              ,y
              ,num_less
              ,num_b
              ,num_b / nullif(num_less,0) as percent_b 
          from (select x
                      ,y
                      ,(select count(*) from table b where b.x<a.x) as num_less
                      ,(select count(*) from table b where b.x<a.x and b.y = 'B') as num_b
                  from table a
               )
         where num_b / nullif(num_less,0) >= 0.99
        );

内部选择执行以下操作:

对于X的每个值

  • 计算nr值&lt; X
  • 计算'B'的nr

下一个SELECT计算B的比率,并仅过滤比率高于阈值的行。外部只从剩余的行中选取max(x)。

修改: 上述查询中的不可缩放部分是半笛卡尔自连接。

答案 1 :(得分:1)

这主要受到前一个答案的启发,这个答案存在一些缺陷。

select max(next_x) from
(
    select 
        count(case when y='B' then 1 end) over (order by x) correct,
        count(case when y='G' then 1 end) over (order by x) wrong,
        lead(x) over (order by x) next_x
    from  table_name
)
where correct/(correct + wrong) > 0.99

示例数据:

create table table_name(x number, y varchar2(1));

insert into table_name
select 2,  'B' from dual union all
select 3,  'B' from dual union all
select 3,  'B' from dual union all
select 4,  'B' from dual union all
select 5,  'B' from dual union all
select 5,  'B' from dual union all
select 5,  'B' from dual union all
select 6,  'G' from dual union all
select 7,  'B' from dual union all
select 7,  'B' from dual union all
select 7,  'B' from dual union all
select 8,  'B' from dual union all
select 8,  'B' from dual union all
select 8,  'B' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 12, 'G' from dual union all
select 13, 'G' from dual union all
select 13, 'G' from dual union all
select 13, 'B' from dual union all
select 13, 'G' from dual union all
select 13, 'G' from dual union all
select 13, 'G' from dual union all
select 13, 'G' from dual union all
select 13, 'G' from dual union all
select 14, 'B' from dual union all
select 14, 'G' from dual union all
select 14, 'G' from dual;

答案 2 :(得分:0)

试试这个并分享结果:

假设表名为table_name,列为x和y

with TAB AS (
select (count(x) over (PARTITION BY Y order by x rows between unbounded preceding and current row))/
       (COUNT(case when y='B' then 1 end) OVER (PARTITION BY Y)) * 100 CC, x, y
  from table_name)
select x,y from (SELECT min(cc) over (partition by y) min_cc, x, cc, y
                   FROM TAB
                  where cc >= 99)
where min_cc = cc