Oracle SQL -聚合乘法

zsohkypk  于 2023-11-17  发布在  Oracle
关注(0)|答案(3)|浏览(160)

我有数据在以下方式:

ITEM     PERCENTAGE
MOBILE | 2
MOBILE | 5
TABLET | 5
TABLET | 3

字符串
我想应用的百分比(如2和5的项目:移动的),
(1-PERCENTAGE_1%) * (1-PERCENTAGE_2%)-顺序无关紧要
最终结果为

ITEM     PERCENTAGE
MOBILE | 0.931
TABLET | 0.9215

ruarlubt

ruarlubt1#

您可以使用lnexp函数将乘法转换为加法,反之亦然。但是它会增加一些舍入误差,如果乘数的数量很大或它们的值太稀疏,则可能会很明显。

select
  item,
  round(exp(sum(ln(1 - PERCENTAGE/100))), 5) as mult
from sample
group by item

字符串
或者使用model clause执行逐行迭代,而不使用ln/exp时出现的近似。

with calc as (
  select *
  from sample
  model
    partition by (item)
    dimension by (row_number() over(partition by item order by null) as dim)
    measures (PERCENTAGE as mult, 0 as last_row)
    rules update (
      mult[any] order by dim = coalesce(mult[cv() - 1], 1)*(1 - mult[cv()]/100),
      /*Last row indicator that will contain aggregated value*/
      last_row[any] = decode(last_row[cv()+1], null, 1, 0)
    )
)
select
  item,
  mult
from calc
where last_row = 1


或者定义本地PL/SQL函数,该函数将遍历乘数集合并执行乘法。然后将其应用于collect聚合函数的结果。Oracle为table of number预定义了sys.ODCINumberList类型。

with function f_mult(nums sys.odcinumberlist)
  return number
as
  pragma udf;
  mult number := 1;
begin
  for i in 1..nums.count() loop
    mult := mult * (1 - nums(i)/100);
  end loop;
  return mult;
end;

select
  item,
  f_mult(cast(collect(PERCENTAGE) as sys.odcinumberlist)) as agg
from sample
group by item


对于您的示例数据:

create table sample(ITEM, PERCENTAGE) as
select 'MOBILE', 2 from dual union all
select 'MOBILE', 5 from dual union all
select 'TABLET', 5 from dual union all
select 'TABLET', 3 from dual


所有上述查询返回相同的结果:
| 项目|AGG|
| --|--|
| 移动的|点九三一口径|
| 平板|.9215|
fiddle

jdgnovmf

jdgnovmf2#

由于项目是成对出现的,一种选择是使用lead解析函数并计算两个值:
样本数据:

SQL> with test (item, percentage) as
  2    (select 'mobile', 2 from dual union all
  3     select 'mobile', 5 from dual union all
  4     select 'tablet', 5 from dual union all
  5     select 'tablet', 3 from dual
  6    ),

字符串
查询:

7  temp as
  8    (select item,
  9            percentage / 100 pct,
 10            lead(percentage/100) over (partition by item order by null) pct2
 11     from test
 12    )
 13  select item,
 14         (1 - pct) * (1 - pct2) percentage
 15  from temp
 16  where pct2 is not null;

ITEM   PERCENTAGE
------ ----------
mobile       ,931
tablet      ,9215

SQL>

j8ag8udp

j8ag8udp3#

这是一种使用解析函数FIRST_VALUELAST_VALUE的方法:

with cte as (
  select ITEM, ( 1 - FIRST_VALUE(percentage) over (partition by item)/100) 
             * ( 1 - LAST_VALUE(percentage) over (partition by item)/100) as PERCENTAGE,
         row_number() over (partition by item order by null) as rn
  from mytable
)
select ITEM, PERCENTAGE
from cte
where rn = 1

字符串
Demo here

相关问题