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

查询以计算Oracle db CLOB列中的不同值,oracle,clob,Oracle,Clob,我想查询Oracle DB表中包含CLOB列中每个不同值的行数 这将返回包含值的所有行: select * from mytable where dbms_lob.instr(mycol,'value') > 0; 使用,返回包含该值的行数: select count(*) from mytable where dbms_lob.instr(mycol,'value') > 0; 但是可以查询每个不同值出现的行数吗 根据该列实际包含的内容,查看是否使用CHAR 根据该列实际包含的

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

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

select * from mytable where dbms_lob.instr(mycol,'value') > 0;
使用,返回包含该值的行数:

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

但是可以查询每个不同值出现的行数吗

根据该列实际包含的内容,查看是否使用CHAR


根据该列实际包含的内容,查看是否使用CHAR


标准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;

另外,请注意,散列冲突的可能性很小。但如果您同意,可以使用这种方法。

标准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;

另外,请注意,散列冲突的可能性很小。但是如果你同意的话,你可以使用这种方法。

如果你的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);

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

这将得到ORA-22835:缓冲区太小。。。如果12cR2+中的任何CLOB值超过4k或可能超过32k,则不确定。如果所有的值都小于这个极限,那么我想你会质疑CLOB的使用——这可能就是你第一句话所指的?是的,@Alex,这就是我的意思。关于OP发布的代码,看起来该列可能包含一个单词,因为他们正在寻找值。如果有一个完整的句子或段落,或者…,count就没有意义了,因为这个组可能总是会导致count等于1。这当然会导致您所说的:在这种情况下,CLOB数据类型的用途是什么。这将导致ORA-22835:缓冲区太小。。。如果12cR2+中的任何CLOB值超过4k或可能超过32k,则不确定。如果所有的值都小于这个极限,那么我想你会质疑CLOB的使用——这可能就是你第一句话所指的?是的,@Alex,这就是我的意思。关于OP发布的代码,看起来该列可能包含一个单词,因为他们正在寻找值。如果有一个完整的句子或段落,或者…,count就没有意义了,因为这个组可能总是会导致count等于1。这当然会引出您所说的:在本例中,CLOB数据类型的目的是什么;稍后,您会说“该行”中每个唯一值的计数-这意味着什么?;标题很模糊。。。你到底想要哪一个?说得好。我实际上是在寻找每个值的计数,即有多少行包含该值。我对我的问题进行了编辑,以反映这一点。第一句话说,您需要不同值的数量;稍后,您会说“该行”中每个唯一值的计数-这意味着什么?;标题很模糊。。。你到底想要哪一个?说得好。我实际上是在寻找每个值的计数,即有多少行包含该值。我编辑了我的问题,以反映.dbms_加密常量在SQL调用中不被识别,至少在12cR1以下;在以后的版本中允许吗?这是文字3而不是那个引用,但很奇怪…@AlexPoole,实际上,不知道那个东西。更改了答案,谢谢。无法识别dbms_加密常量i
n个SQL调用,至少高达12cR1;在以后的版本中允许吗?这是文字3而不是那个引用,但很奇怪…@AlexPoole,实际上,不知道那个东西。更改了答案,谢谢。