查询以计算Oracle db CLOB列中的不同值

时间:2019-04-09 17:11:16

标签: oracle clob

我想在Oracle DB表中查询包含CLOB列中每个不同值的行数。

这将返回包含值的所有行:

select * from mytable where dbms_lob.instr(mycol,'value') > 0;

使用DBMS_LOB,返回包含该值的行数:

select count(*) from mytable where dbms_lob.instr(mycol,'value') > 0;

但是是否可以查询每个不同值出现的次数(行数)?

3 个答案:

答案 0 :(得分:2)

根据该列实际包含的内容,查看TO_CHAR是否有帮助。

SQL> create table mytable (mycol clob);

Table created.

SQL> insert into mytable
  2    select 'Query to count distinct values' from dual union all
  3    select 'I have no idea which values are popular' from dual;

2 rows created.

SQL>  select count(*), to_char(mycol) toc
  2  from mytable
  3  where dbms_lob.instr(mycol,'value') > 0
  4  group by to_char(mycol);

  COUNT(*) TOC
---------- ----------------------------------------
         1 Query to count distinct values
         1 I have no idea which values are popular

SQL>

答案 1 :(得分:2)

标准Oracle函数不支持CLOB值的区分。但是,如果可以访问DBMS_CRYPTO.HASH函数,则可以比较CLOB哈希,从而获得所需的输出:

select myCol, h.num from
   myTable t join 
      (select min(rowid) rid, count(rowid) num
              from myTable
       where dbms_lob.instr(mycol,'value') > 0
       group by DBMS_CRYPTO.HASH(myCol, 3)) h
   on t.rowid = h.rid;

另外,请注意,哈希冲突的可能性很小。但是,如果您认为可以,则可以使用这种方法。

答案 2 :(得分:2)

如果您的CLOB值超过4000个字节(如果不是,为什么要使用它们CLOB?),这并不完美-如果不太可能发生冲突,但是您可以散列CLOB值。

如果要计算不同值的数量:

select count(distinct dbms_crypto.hash(src=>mycol, typ=>2))
from mytable
where dbms_lob.instr(mycol,'value') > 0;

如果您要计算每个不同值出现的次数:

select mycol, cnt
from (
  select mycol,
    count(*) over (partition by dbms_crypto.hash(src=>mycol, typ=>2)) as cnt,
    row_number() over (partition by dbms_crypto.hash(src=>mycol, typ=>2) order by null) as rn
  from mytable
  where dbms_lob.instr(mycol,'value') > 0
)
where rn = 1;

两者可能都相当昂贵,并且处理大量数据的速度很慢。

({typ=>2给出dbms_crypto.hash_md5的数值,因为您不能在SQL调用中引用程序包常量,至少不超过12cR1 ...)


更粗略,但可能更快得多,您可以基于前4000个字符进行计数-对于您的实际数据而言,这可能是合理的,也可能不是合理的:

select count(distinct dbms_lob.substr(mycol, 4000, 1))
from mytable
where dbms_lob.instr(mycol,'value') > 0;

select dbms_lob.substr(mycol, 4000, 1), count(*)
from mytable
where dbms_lob.instr(mycol,'value') > 0
group by dbms_lob.substr(mycol, 4000, 1);