2013-04-17 80 views
2

我正在比较一个表与自己,试图确定一个记录中的电子邮件是否正在其他记录中的其他四个列中的任何一个中使用。用于不同记录比较的Sql

为了更方便,让我们来看一个例子(简体):

Name: Bob 
Office Email: [email protected] 
Home Email: [email protected] 
Mobile Email: [email protected] 

Name: Rob 
Office Email: [email protected] 
Home Email: [email protected] 
Mobile Email: [email protected] 

现在我有一个sql语句是这样的:

select c1.ContactId id1, c1.FullName Name1, 'Office Email 1' EmailType1, c1.EMailAddress1 Email, 
    c2.ContactId id2, c2.FullName Name2, 
    CASE c1.EmailAddress1 
    WHEN c2.EMailAddress1 THEN 'Office Email 1' 
    WHEN c2.Si_OfficeEmail2nd THEN 'Office Email 2' 
    WHEN c2.EMailAddress2 THEN 'Mobile Email' 
    WHEN c2.pc_hmemail THEN 'Home Email' 
    ELSE '?' 
    END EmailType2, 
    CASE c1.EmailAddress1 
    WHEN c2.EMailAddress1 THEN c2.EMailAddress1 
    WHEN c2.Si_OfficeEmail2nd THEN c2.Si_OfficeEmail2nd 
    WHEN c2.EMailAddress2 THEN c2.EMailAddress2 
    WHEN c2.pc_hmemail THEN c2.pc_hmemail 
    ELSE '?' 
    END DuplicateEmail 
from Contact c1, Contact c2 
where (
    LTRIM(RTRIM(c1.EMailAddress1)) = LTRIM(RTRIM(c2.EMailAddress1)) 
Or LTRIM(RTRIM(c1.EMailAddress1)) = LTRIM(RTRIM(c2.EMailAddress2)) 
Or LTRIM(RTRIM(c1.EMailAddress1)) = LTRIM(RTRIM(c2.pc_hmemail)) 
Or LTRIM(RTRIM(c1.EMailAddress1)) = LTRIM(RTRIM(c2.Si_OfficeEmail2nd)) 
) 
And c1.ContactId <> c2.ContactId 
And c1.StateCode = 0 
and c2.StateCode = 0 
order by c1.FullName, c2.FullName 

不幸的是,因为鲍勃和Rob有相同的电子邮件“类型”(主页电子邮件)因复制到一个错字,我的查询返回两条记录,其中一条显示鲍勃斯电子邮件在Robs电子邮件中被复制,另一个Robs电子邮件被复制到鲍勃斯电子邮件中。

我只需要一条记录。我确定这是一个常见问题,但我不太清楚如何描述这个问题,以便让搜索引擎返回一些有用的信息。

也许有更好的方法去做这件事?如果不是,除了跳过一堆中间临时表以消除这些等效记录外,是否有办法为此编写单个查询?

+0

如果能够正常化你的数据库,这样做。联系人和电子邮件地址之间的一对多关系是适当的。然后,您可以对电子邮件地址和类型进行独特的限制。另外,如果Bob和Rob真的拥有相同的家庭电子邮件呢?我和我的妻子呢。 –

+0

不幸的是,我无法正常化数据库,我正在使用MS CRM 2011,这些电子邮件是股票(除了一个,但在这一点上是无关紧要的)。 – Bitfiddler

回答

1

解决您的问题是添加条件:c1.contactId < c2.ContactId。这限制了你正在看的对子。

如果您正在查看电子邮件,您可能会发现一种更直接查看电子邮件的更快方法。类似以下内容将返回所有重复邮件(在单独的行上):

select e.* 
from (select e.*, COUNT(*) over (partition by email) as NumTimes 
     from ((select contactId, 'Office' as which, EmailAddress1 as email 
      from Contact 
      ) union all 
      (select contactId, 'Office2', Si_OfficeEmail2nd 
      from Contact 
      ) union all 
      (select contact_id, 'Home', pc_hmemail 
      from Contact 
      ) union all 
      (select contact_id, 'Mobile', EmailAddress2 
      from Contact 
      ) 
      ) e 
     where email is not null and email <> '' 
    ) e 
where NumTimes > 1 
order by email 
+0

非常酷的方法。非常感谢,我会试试看,如果它符合我的想法,我会很快将其标记为解决方案。 – Bitfiddler

+0

不错,结合了你的建议,既快速又准确。我希望我能给你买一杯啤酒! – Bitfiddler

0

我首先建议继续规范化您的数据结构。一个人可能有几种类型的联系信息。因此personID,typeID和value可以放在另一个表中。从此表中您可以创建与类型表的另一种关系,您可以跟踪不同的联系人类型(例如家庭电子邮件,工作电子邮件,Twitter,linkedIn,Facebook等)。它不仅可以提高系统的可扩展性,还可以更高效地运行这些类型的查询。

SELECT user.username FROM user u LEFT JOIN contactinfo ci ON u.user_id=ci.user_id LEFT JOIN contacttype ct ON ci.type_id=ct.type_id GROUP BY ci.value HAVING count(value)>1将查询找到任何重复的来源

+0

不幸的是,我不能规范化数据库,我正在使用MS CRM 2011,这些电子邮件是股票(除了一个,但在这一点上是无关紧要的)。 – Bitfiddler