我有一个表客户,列cid,mobile_no。 cid是独一无二的。 mobile_no有多个以逗号或引号分隔的移动号码。该表包含超过10万条记录。现在,如果我将一个电话号码作为一个客户的输入,并且基于我需要获取cid然后将其与另一个表客户详细信息一起映射以获取值,我该如何处理?我不能使用like运算符,因为对于记录超过100k的表来说它会非常重。
例如:
cid_1 9263532727," 9738262783" ....
cid_2' 8745362664,"' 6384683633'&#34 ;; ...
上述示例可视为手机号码的场景之一。 现在,如果我得到6384683633作为手机号码,我需要获取cid和地图与其他表格来获取客户的详细信息。
我可以将like
运算符与'%%'
一起使用,但这会使查询效率低下。
还有其他办法吗?
答案 0 :(得分:2)
首先,是的 - 更改数据模型。
这是在看到@Dipanshu的评论后写的,还要求另一种选择。
这种方法的想法是将移动电话号码分成行(这是SPLIT_ME所做的),然后简单地选择是否有任何匹配搜索字符串的信息。
SQL> with test (id, mobile_no) as
2 (select 1, '9263532727,9738262783' from dual union
3 select 2, '8745362664,6384683633,9876543210' from dual
4 ),
5 split_me as
6 (select id, regexp_substr(mobile_no, '[^,]+', 1, column_value) mobile_no
7 from test,
8 table(cast(multiset(select level from dual
9 connect by level <= regexp_count(mobile_no, ',') + 1
10 ) as sys.odcinumberlist))
11 )
12 select * From split_me
13 where mobile_no = &search_mobile_no;
Enter value for search_mobile_no: 9876543210
ID MOBILE_NO
---------- --------------------------------
2 9876543210
SQL>
答案 1 :(得分:1)
建议#1:
不要采用这种设计
建议#2:
如果 使用此设计,则可以使用Text索引来解析索引的值,例如
SQL> create table t ( cid int, mobs varchar2(1000));
Table created.
SQL>
SQL> insert into t
2 select c, listagg(num,',') within group ( order by num )
3 from
4 ( select mod(rownum,1000) c, trunc(dbms_random.value(1000000,9999999)) num from dual connect by level <= 4000 )
5 group by c;
1000 rows created.
SQL>
SQL> select * from t
2 where rownum <= 10;
CID MOBS
---------- --------------------------------------------------
710 1309670,2250891,2446498,6381871
711 6441062,7421544,8803290,8980956
712 5216092,6664995,7971562,8615836
713 2699908,4060187,7669498,8998292
714 2565735,2621571,4071919,9443984
715 1284533,2445570,6669291,8675917
716 2368712,4074744,7804389,9798070
717 1037619,4071820,4235448,7026192
718 2955831,6282004,7131543,9027507
719 4040856,4761599,4859829,9179022
10 rows selected.
SQL>
SQL> begin
2 ctx_ddl.drop_preference('my_lexer');
3 ctx_ddl.create_preference('my_lexer', 'BASIC_LEXER');
4 ctx_ddl.set_attribute('my_lexer', 'numgroup', '~');
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
SQL> create index ix on t ( mobs ) indextype is ctxsys.context PARAMETERS('lexer my_lexer');
Index created.
SQL> set autotrace on
SQL> select * from t
2 where contains(mobs,'7804389') > 0;
CID MOBS
---------- --------------------------------------------------
716 2368712,4074744,7804389,9798070
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1339481741
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 527 | 4 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 527 | 4 (0)| 00:00:01 |
|* 2 | DOMAIN INDEX | IX | | | 4 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("CTXSYS"."CONTAINS"("MOBS",'7804389')>0)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
Statistics
----------------------------------------------------------
196 recursive calls
0 db block gets
152 consistent gets
1 physical reads
0 redo size
640 bytes sent via SQL*Net to client
608 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
SQL>