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

问题描述 投票:0回答:3

我想在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;

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

oracle clob
3个回答
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>

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);

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;

另外,请注意,哈希冲突的可能性很小。但如果你没问题,可以使用这种方法。

© www.soinside.com 2019 - 2024. All rights reserved.