我想在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;
但是是否可以查询每个不同值出现的次数(行数)?
答案 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);