从另一个表中选择带有子字符串的记录

时间:2010-10-26 20:53:55

标签: sql-server sql-server-2008 stored-procedures

我有两张桌子:

data    
id   |email    
_   
1    |xxx@gmail.com    
2    |yyy@gmial.com    
3    |zzzgimail.com 

errors    
_    
error    |correct    
@gmial.com|@gmail.com    
gimail.com|@gmail.com    

如何从data中选择包含电子邮件错误的所有记录?感谢。

4 个答案:

答案 0 :(得分:1)

假设错误总是在字符串的末尾:

declare @data table (
    id int,
    email varchar(100)
)

insert into @data
    (id, email)
    select 1, 'xxx@gmail.com' union all
    select 2, 'yyy@gmial.com' union all
    select 3, 'zzzgimail.com'

declare @errors table (
    error varchar(100),
    correct varchar(100)
)

insert into @errors
    (error, correct)
    select '@gmial.com', '@gmail.com' union all
    select 'gimail.com', '@gmail.com'   

select d.id, 
       d.email, 
       isnull(replace(d.email, e.error, e.correct), d.email) as CorrectedEmail
    from @data d
        left join @errors e
            on right(d.email, LEN(e.error)) = e.error

答案 1 :(得分:1)

SELECT d.id, d.email
FROM data d
    INNER JOIN errors e ON d.email LIKE '%' + e.error

会这样做,但是在匹配的值的开始处使用通配符执行LIKE将阻止使用索引,因此您可能会看到性能不佳。

最佳方法是在数据表上定义计算列,即电子邮件字段的REVERSE并对其进行索引。这会将上面的查询转换为LIKE条件,最后使用通配符,如下所示:

SELECT d.id, d.email
FROM data d
    INNER JOIN errors e ON d.emailreversed LIKE REVERSE(e.error) + '%'

在这种情况下,性能会更好,因为它允许使用索引。

我在博客上写了一篇关于这种方法的完整文章a while ago here

答案 2 :(得分:0)

嗯,实际上你不能使用你提供的信息。

在SQL中,您需要维护一个“正确”域的表。有了它,你可以做一个简单的查询来找到不匹配。

您可以在SQL Server中使用某些“非”SQL功能来执行正则表达式检查,但是这种逻辑在SQL(IMO)中不会低于此类。

答案 3 :(得分:0)

select * from 
(select 1 as id, 'xxx@gmail.com' as email union
 select 2 as id, 'yyy@gmial.com' as email union
 select 3 as id, 'zzzgimail.com' as email) data join

(select '@gmial.com' as error, '@gmail.com' as correct union
 select 'gimail.com' as error, '@gmail.com' as correct ) errors

 on data.email like '%' + error + '%' 

我认为......如果您在开始时没有使用通配符,但在之后的任何地方,它可以从索引中受益。如果您使用全文搜索,它也可能会受益。