我有一个表,其中包含数百万行的客户名称列。我想查找同一列的另一行中是否存在名称的一部分。 例如。如果一行具有值“ Roger Federer”,并且还有其他行具有值“ Roger”和“ Federer”,则我希望所有三行都具有对应的主键。
答案 0 :(得分:3)
您可以利用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)
答案 1 :(得分:2)
如果您想构造与行相关的逻辑,则union
概念可能很合适,
顺便说一句,在字符串操作中,我们最好通过upper
或lower
函数将排序规则与模式配合使用,以满足字母的不区分大小写的要求:
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