如何在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
概念可能很适合,
顺便说一句,在字符串操作中,我们最好通过 upper
或 lower
函数使用带模式的排序规则来满足字母的 不区分大小写 :
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')
可以找到 REGEXP_LIKE 用法的更多示例 here
另一种选择是使用 OR
SELECT *
FROM customers
WHERE LOWER(cust_name) LIKE LOWER('%roger%')
OR LOWER(cust_name) LIKE LOWER('%federer%')
编辑
通过使用 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)
编辑 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)
我认为您可以使用 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
我有一个 table,其中包含数百万行客户姓名列。我想查找名称的一部分是否存在于同一列的另一行中。 例如。如果一行的值为 'Roger Federer' 并且其他行的值为 'Roger' 和 'Federer',我需要所有三行的相应主键。
如果您想构建与行相关的逻辑,union
概念可能很适合,
顺便说一句,在字符串操作中,我们最好通过 upper
或 lower
函数使用带模式的排序规则来满足字母的 不区分大小写 :
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')
可以找到 REGEXP_LIKE 用法的更多示例 here
另一种选择是使用 OR
SELECT *
FROM customers
WHERE LOWER(cust_name) LIKE LOWER('%roger%')
OR LOWER(cust_name) LIKE LOWER('%federer%')
编辑
通过使用 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)
编辑 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)
我认为您可以使用 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