我有一个充满客户数据的SAP Oracle数据库.
在我们的自定义CRM中,使用通配符搜索客户是很常见的.除了SAP标准搜索之外,我们还想对一些类似于输入名称的名称进行模糊文本搜索.
目前我们正在使用UTL_MATCH.EDIT_DISTANCE函数来搜索类似的名称.唯一的缺点是不可能使用一些通配符模式.
在我们的自定义CRM中,使用通配符搜索客户是很常见的.除了SAP标准搜索之外,我们还想对一些类似于输入名称的名称进行模糊文本搜索.
目前我们正在使用UTL_MATCH.EDIT_DISTANCE函数来搜索类似的名称.唯一的缺点是不可能使用一些通配符模式.
是否有可能将通配符与UTL_MATCH.EDIT_DISTANCE函数结合使用,或者有不同(甚至更好)的方法吗?
PATRICK NOR ORVILLE ALEX OWEN TRISTAN OKEN TRIST
查询看起来像OKEN * IST *,并且应该返回OWEN TRISTAN和OKEN TRISTAN. OKEN将是100%的比赛而OWEN则更少.
我目前的测试查询如下:
SELECT gp.partner,gp.bu_sort1,UTL_MATCH.edit_distance(gp.bu_sort1,?) as edit_distance,FROM but000 gp WHERE UTL_MATCH.edit_distance(gp.bu_sort1,?) < 4
请注意您的方法在表现方面的含义.即使它在“功能上”起作用,使用UTL_MATCH也只能过滤内部表扫描获得的结果.
你可能需要的是这些数据的索引.
前往Oracle Text,Oracle的文本索引功能.请记住,他们需要付出一些努力才能投入工作.
你可能需要的是这些数据的索引.
前往Oracle Text,Oracle的文本索引功能.请记住,他们需要付出一些努力才能投入工作.
您可能会使用模糊运算符,但要小心处理.大多数oracle文本功能都依赖于语言(它们考虑了英语词典,德语等).
例如
-- create and populate the table create table xxx_names (name varchar2(100)); insert into xxx_names(name) values('PATRICK NOR'); insert into xxx_names(name) values('ORVILLE ALEX'); insert into xxx_names(name) values('OWEN TRISTAN'); insert into xxx_names(name) values('OKEN TRIST'); insert into xxx_names(name) values('OKENOR SAD'); insert into xxx_names(name) values('OKENEAR TRUST'); --create the domain index create index xxx_names_ctx on xxx_names(name) indextype is ctxsys.context;
此查询将返回您可能喜欢的结果(输入为字符串“TRST”)
select score(1),name from xxx_names n where CONTAINS(n.name,'definescore(fuzzy(TRST,1,6,weight),relevance)',1) > 0 ; score(1) NAME ---------- -------------------- 1 OWEN TRISTAN 22 OKEN TRIST
但是使用输入字符串“IST”它可能不会返回任何内容(在我的情况下,这就是它的作用).
另请注意,通常,默认情况下,少于3个字符的输入被视为不匹配.
如果您取消“模糊”要求并坚持找到仅包含您传入的确切序列的行,您可能会获得更“可预测”的结果.
在这种情况下尝试使用ctxcat索引,顺便说一下,它支持一些通配符(警告:支持多列,但列的大小不能超过30个字符!)
-- create and populate the table --max length is 30 chars,otherwise the catsearch index can't be created create table xxx_names (name varchar2(30)); insert into xxx_names(name) values('PATRICK NOR'); insert into xxx_names(name) values('ORVILLE ALEX'); insert into xxx_names(name) values('OWEN TRISTAN'); insert into xxx_names(name) values('OKEN TRIST'); insert into xxx_names(name) values('OKENOR SAD'); insert into xxx_names(name) values('OKENEAR TRUST'); begin ctx_ddl.create_index_set('xxx_names_set'); ctx_ddl.add_index('xxx_names_set','name'); end; / drop index xxx_names_cat; CREATE INDEX xxx_names_cat ON xxx_names(name) INDEXTYPE IS CTXSYS.CTXCAT PARAMETERS ('index set xxx_names_set');
后者,使用此查询可以很好地工作(输入是“* TRIST *”)
select UTL_MATCH.edit_distance(name,'TRIST') dist,name from xxx_names where catsearch(name,'*TRIST*','order by name desc') > 0 ; DIST NAME ---------- -------------------- 7 OWEN TRISTAN 5 OKEN TRIST
但是输入“* O * TRIST *”不会返回任何内容(由于某些原因).
底线:文本索引可能是唯一的方法(性能),但你必须弄清楚了解所有的复杂性.
参考文献:
>模糊搜索:Oracle Text CONTAINS Query Operators
> catsearch:Oracle Text SQL Statements and Operators