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

How to search if a row is a substring of another row of the same column in Oracle

我有一个 table,其中包含数百万行客户姓名列。我想查找名称的一部分是否存在于同一列的另一行中。 例如。如果一行的值为 'Roger Federer' 并且其他行的值为 'Roger' 和 'Federer',我需要所有三行的相应主键。

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

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

select id from customers where lower(name) like '%roger%' union all
select id from customers where lower(name) like '%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') 使查询更加动态,如您所愿。 (当出现提示时,输入 Roger Federer 作为 str 替换变量)

您可以利用 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

我认为您可以使用 join same table 两次(自连接)来获取以下查询的输出,

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