从列中过滤数据的有效方法,移动号码由特殊字符分隔。 column具有varchar2数据类型的编号

时间:2018-02-06 10:07:08

标签: sql oracle plsql oracle11g

我有一个表客户,列cid,mobile_no。 cid是独一无二的。 mobile_no有多个以逗号或引号分隔的移动号码。该表包含超过10万条记录。现在,如果我将一个电话号码作为一个客户的输入,并且基于我需要获取cid然后将其与另一个表客户详细信息一起映射以获取值,我该如何处理?我不能使用like运算符,因为对于记录超过100k的表来说它会非常重。

例如:

ID mobile_no

cid_1 9263532727," 9738262783" ....
cid_2' 8745362664,"' 6384683633'&#34 ;; ...

上述示例可视为手机号码的场景之一。 现在,如果我得到6384683633作为手机号码,我需要获取cid和地图与其他表格来获取客户的详细信息。

我可以将like运算符与'%%'一起使用,但这会使查询效率低下。

还有其他办法吗?

2 个答案:

答案 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>