如何搜索一行是否是Oracle中同一列的另一行的子字符串

时间:2018-08-28 15:08:27

标签: sql oracle oracle11g query-string

我有一个表,其中包含数百万行的客户名称列。我想查找同一列的另一行中是否存在名称的一部分。 例如。如果一行具有值“ Roger Federer”,并且还有其他行具有值“ Roger”和“ Federer”,则我希望所有三行都具有对应的主键。

3 个答案:

答案 0 :(得分:3)

您可以利用REGEXP_LIKE

 SELECT * 
    FROM   customers    
    WHERE REGEXP_LIKE (cust_name, 'roger|federer','i')

SQL Fiddle Demo

更多关于REGEXP_LIKE用法的示例,here

另一个选择是使用OR

SELECT * 
    FROM   customers    
        WHERE LOWER(cust_name) LIKE LOWER('%roger%')
    OR LOWER(cust_name) LIKE LOWER('%federer%')

SQL Fiddle Demo

编辑

使用JOIN,搜索字符串是动态的。如果适当的索引到位,那么不会有太大影响。

SELECT DISTINCT
   c1.*
FROM
   customers c1 
   JOIN
      customers c2
      ON ( LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%') 
      AND c1.cust_id != c2.cust_id)

SQL Fiddle Demo

编辑2

也许像下面这样

SELECT DISTINCT
   c1.cust_id,
   c1.cust_name,
   CASE
      WHEN
         LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%') 
      THEN
         'Matched' 
      ELSE
         'Unmatched' 
   END
   ident 
FROM
   customers c1 
   JOIN
      customers c2 
      ON ( LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%') 
      AND c1.cust_id != c2.cust_id)

SQL Fiddle Demo

答案 1 :(得分:2)

如果您想构造与行相关的逻辑,则union概念可能很合适,

顺便说一句,在字符串操作中,我们最好通过upperlower函数将排序规则与模式配合使用,以满足字母的不区分大小写的要求:

select id from customers where lower(name) like '%roger%' union all
select id from customers where lower(name) like '%federer%';

,无需添加 已经包含的 完整名称(例如 Roger Federer )。

编辑: Alternative method可能如下:

  select distinct id
    from (select lower(regexp_substr('&str', '[^[:space:]-]+', 1, 1)) frst,
                 lower(regexp_substr('&str', '[^[:space:]-]+', 1, 2)) lst,
                 lower('&str') nm
            from customers) c1
   cross join customers c2
   where c1.frst like '%' || lower(c2.name) || '%'
      or c1.lst like '%' || lower(c2.name) || '%'
      or c1.nm like '%' || lower(c2.name) || '%';

通过添加搜索字符串('&str')使查询更加动态。 (当提示输入str替换变量的Roger Federer时)

答案 2 :(得分:1)

我认为您可以使用同一张表两次来通过以下查询获取输出,

select a.*, b.* 
  from tab1 a 
      , tab1 b
where ( a.fname like b.fname||'%' or a.lname like b.lname||'%')
  and a.id <> b.id