我有一个为大量区域定义的电话号码前缀列表(在由gvcode和cgi定义的查询中)。 我需要有效地找到与给定数字PHONE_NR匹配的最长前缀。
我在字段数字上使用倒置LIKE子句(其中包含格式为+ 48%,+ 49%,+ 1%,+ 1232%等的前缀)。
因此我不能在该字段上使用普通索引。
通过在gvcode和cgi字段上使用IOT(这是主键的一部分(前两个列)),我设法获得了实质性的改进。 我还查看了一些oracle文本索引,但找不到一个匹配表中较短前缀的较长输入。
是否还有其他方法可以执行比此方法更快的搜索。
这是一个查询,它给出了所有匹配前缀的列表(我之后按数字长度对其进行排序)。
select t.gvcode, t.digits
from NUMBERS t
where
t.gvcode=ZONE_SET_CODE
and t.cgi=cgi_f
and ( PHONE_NR like t.digits)
order by length(digits) desc
答案 0 :(得分:1)
我可能听起来很愚蠢,但当我遇到这样的问题时,我进入了大多数非节省空间的蛮力方式:
让我们说:
L=length of longest prefix to match (without obvious +, of course)
添加L
个命名的其他字段,例如P1, P2,...,PL
使用
更新这些字段UPDATE NUMBERS set P1=SUBSTR(PHONE_NR,1,1), P2=SUBSTR(PHONE_NR,1,2), ..., PL=SUBSTR(PHONE_NR,1,L)
(将来你也可以在INSERT OR UPDATE
触发器中执行此操作)
现在你有L个字段来创建索引并与你喜欢的任何东西进行比较。
答案 1 :(得分:1)
除了“数字”索引外,您还可以在rpad(substr(digits,1,length(digits)-1), 10, '9')
上创建索引。 “10”是您要支持的最大长度。您将在where子句中添加一个附加条件:rpad(substr(digits,1,length(digits)-1), 10, '9') >= PHONE_NR
您的SQL将是:
select t.gvcode, t.digits
from NUMBERS t
where
t.gvcode=ZONE_SET_CODE
and t.cgi=cgi_f
and PHONE_NR like t.digits
and substr(digits, 1, length(digits)-1) <= PHONE_NR
and rpad(substr(digits,1,length(digits)-1), 10, '9') >= PHONE_NR
order by length(digits) desc
以下是sqlfiddle
中的示例答案 2 :(得分:1)
我遇到了同样的问题,我发现此解决方案很有用(在https://community.oracle.com/thread/351988上归功于L. Schneider):
create table a (a varchar2(100));
create index a_1 on a(a);
begin
delete a;
insert into a values ('00431');
insert into a values ('004312');
insert into a values ('0043123');
insert into a values ('00431234');
insert into a values ('004312345');
end;
/
select max(a)
from a
where '004311' like a||'%'
;
答案 3 :(得分:0)
我不确定这会有什么帮助,但我认为值得一试。
在substr(digits, 1, length(digits)-1)
上创建基于函数的索引(这仅用于索引没有'%'的数字)
然后在您的查询中,您可以添加另一个条件:
AND substr(digits, 1, length(digits)-1) <= PHONE_NR
我们的想法是,通过 lexical 比较,您可以“删除”所有数字,这些数字都在PHONE_NR之后
答案 4 :(得分:0)
好的,只是写作,因为我有同样的问题。 如果您知道前缀长度的范围,则可以执行与以下内容类似的操作。以下示例假定前缀长度为2-6
select t.num, coalesce(p6.PREFIX, p5.PREFIX, p4.PREFIX, p3.PREFIX, p2.PREFIX) PREFIX
from NUMBERS t
LEFT OUTER JOIN PREFIXES p2 ON substr(t.num,1,2)=p2.PREFIX
LEFT OUTER JOIN PREFIXES p3 ON substr(t.num,1,3)=p3.PREFIX
LEFT OUTER JOIN PREFIXES p4 ON substr(t.num,1,4)=p4.PREFIX
LEFT OUTER JOIN PREFIXES p5 ON substr(t.num,1,5)=p5.PREFIX
LEFT OUTER JOIN PREFIXES p6 ON substr(t.num,1,6)=p6.PREFIX
平等连接就像你能得到的一样好。
我认为它比其他任何可能的解决方案都要好得多,希望它可以帮助任何偶然发现同一问题的人