我想在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;
但是,是否可以查询每个不同值出现的次数(行)?
根据列真正包含的内容,查看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>
如果你的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);
标准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;
另外,请注意,哈希冲突的可能性很小。但如果你没问题,可以使用这种方法。