通过Oracle中的Case-When语句获取计数或值

时间:2014-07-30 16:49:46

标签: sql performance oracle11g

我可以替换此oracle查询中的子查询以提高性能吗?

我需要根据查询区分1个或多个计数。因此,如果计数为1,则显示该值,否则显示计数(或者在这种情况下,为2表示它大于1,因为确切的数字是无关的)。

select t.refnum,
case count(t.acctnum) 
  when 1 then 
    ( select to_number(a.acctnum) 
      from transactions a 
      where a.refnum = t.refnum)
  else 2 
end as num_accts
from transactions t
group by t.refnum;

REFNUM        NUM_ACCTS
FF000001235   2
FF000001234   123400
FF000001236   456789

输出正确,我只需要提高性能。 Fiddle

编辑:输入

REFNUM        ACCTNUM
FF000001234   123400
FF000001234   123400

我需要它将其视为1条记录,就好像group by refnum, acctnum

一样

1 个答案:

答案 0 :(得分:1)

您可以在子查询中使用分析计数,因此您只需按一次表格:

select refnum,
  case when num_accts = 1 then to_number(acctnum) else 2 end as num_accts
from (
  select refnum,
    acctnum,
    count(acctnum) over (partition by refnum) as num_accts,
    row_number() over (partition by refnum order by null) as refnum_row
  from transactions
)
where refnum_row = 1
order by refnum, refnum_row;

REFNUM       NUM_ACCTS
----------- ----------
FF000001234     123400
FF000001235          2
FF000001236     456789

SQL Fiddle也显示子查询的结果集。构成基表的每一行都由其返回num_accts列,每列具有相同的值refnum。由于您只希望每refnum看到一个结果,因此还有另一个额外的列,在每个refnum中为每行分配行号,而外部查询仅查看第一行。这相当于在外部查询中只有distinct

在这种情况下,refnum内的帐户顺序无关紧要,因为如果只有一个帐户,则只使用实际值;通常order by子句中的over会更有意义......


如果acctnum中的单个refnum有多行,并且您希望将其视为一个,则可以在distinct子句中添加count()

    count(distinct acctnum) over (partition by refnum) as num_accts,

......即:

select refnum,
  case when num_accts = 1 then to_number(acctnum) else 2 end as num_accts
from (
  select refnum,
    acctnum,
    count(distinct acctnum) over (partition by refnum) as num_accts,
    row_number() over (partition by refnum order by null) as refnum_row
  from transactions
)
where refnum_row = 1
order by refnum, refnum_row;

SQL Fiddle包含重复的FF000001234123400示例。