2016-11-15 27 views
2

如果我有这样的Oracle中的集合:ORACLE - 如何计算集合中成员的出现次数?

DECLARE 
    TYPE v_type IS TABLE OF varchar2(4000); 
    v_coll v_type := v_type(); 
    v_num_dups NUMBER; 
BEGIN 
    v_coll.extend(); 
    v_coll(1):= 'not dupe'; 
    v_coll.extend(); 
    v_coll(2):= 'dupe'; 
    v_coll.extend(); 
    v_coll(3):= 'dupe'; 

    for i in 1..v_coll.count loop 
     dbms_output.put_line(v_coll(i)); 
    end loop; 

END; 

我怎么能返回dupe出现组成v_num_dups了计数,而通过收集和循环计数?

有没有简单的方法来说v_coll.count('dupe')或类似的东西?

回答

1

如果您想完全避免重复,可以使用关联数组。喜欢的东西:

DECLARE 
    TYPE v_type IS TABLE OF number index by varchar2(4000); 
    v_coll v_type; 
    idx varchar2(4000); 
BEGIN 
    v_coll('not dupe'):= 1; 
    v_coll('dupe'):= 1; 
    v_coll('dupe'):= 1; 

    -- show key values 
    idx := v_coll.first; 
    loop 
     exit when idx is null; 
     dbms_output.put_line(idx); 
     idx := v_coll.next(idx); 
    end loop; 

END; 

输出:

dupe 
not dupe 
+0

哇,这是伟大的...任何重复只会指向之前添加的最后一个值。如果你想*重复值,我猜它很糟糕,但如果不是,这真是太棒了!谢谢!!! –

0

不幸的是,没有(至少11g)。 您必须手动遍历集合并执行计数。

0

虽然我喜欢tbone的回答,这也工作得非常不错,除去重复:

DECLARE 
    TYPE v_type IS TABLE OF varchar2(4000); 
    v_coll v_type := v_type(); 
    v_num_dups NUMBER; 
BEGIN 
    v_coll.extend(); 
    v_coll(1):= 'not dupe'; 
    v_coll.extend(); 
    v_coll(2):= 'dupe'; 
    v_coll.extend(); 
    v_coll(3):= 'dupe'; 

    v_coll:=SET(v_coll); --<----remove dups! 

    dbms_output.put_line(cardinality(v_coll)); 

    for i in 1..v_coll.count loop 
     dbms_output.put_line(v_coll(i)); 
    end loop; 

END; 
+1

它很好,但很大的卷很慢...... ;-)当你使用tbone建议的方法(我认为是最好的方法)时,要注意空值。如果您将null指定为密钥,则循环将停止正常工作。 – Rusty