PostgreSQL:匹配带或不带子域的电子邮件地址

问题描述

场景

在其历史的大部分时间里,我的公司在电子邮件地址中使用子域,主要是按州,但其他公司则使用部门子域。我们所拥有的一些示例包括

mo.widgits.com
sd.widgits.com
va.widgits.com
nhq.widgits.com
gis.widgits.com
tech.widgits.com

...等等。

新范式

几年前,高层管理人员决定希望我们都成为一个幸福的家庭;作为这种文化调整的一部分,他们将每个人的电子邮件地址更改为单一域,格式为 firstname.lastname@widgits.com

目前的挑战

在我们的许多公司数据库中,我们发现混合使用旧格式和新格式的记录。例如,同一个人可能在员工系统中有 porky.pig@widgits.com,在培训系统中有 porky.pig@in.widgits.com。我需要在各种系统中匹配个人,而不管该系统中为他们使用哪种格式的电子邮件

想要的匹配

porky.pig@in.widgits.com = porky.pig@widgits.com -> true
mary.poppins@widgits.com = mary.poppins@nhq.widgits.com -> true
bob.baker@widgits.com = bob.barker@gis.widgits.com -> false

如何做到这一点?

是否有正则表达式模式可以用来匹配电子邮件地址,而不管它们是哪种格式?或者我是否需要在尝试匹配子域之前手动提取子域?

解决方法

在我看来,您可以在比较之前从所有电子邮件地址中去除子域(即,仅比较电子邮件名称和域)。像这样:

SELECT *
FROM emails
WHERE REGEXP_REPLACE(email1,'^(.*@).*?([^.]+\.[^.]+)$','\1\2') =
      REGEXP_REPLACE(email2,'\1\2');

screen capture from demo link below

Demo

数据:

WITH emails AS (
    SELECT 'porky.pig@in.widgits.com' AS email1,'porky.pig@widgits.com' AS email2 UNION ALL
    SELECT 'mary.poppins@widgits.com','mary.poppins@nhq.widgits.com' UNION ALL
    SELECT 'bob.baker@widgits.com','bob.barker@gis.widgits.com'
)

这里是对使用的正则表达式模式的解释:

^                   start of the email
    (.*@)           match email name including @ in \1
    .*?             consume content up,but not including
    ([^.]+\.[^.]+)  final domain only (e.g. google.com)
$                   end of the email

然后,我们替换为 \1\2 以有效删除任何子域组件。

,

这样的事情怎么样?

SELECT 
  * 
FROM 
  (
    SELECT 
      table1.email,table2.email,SPLIT_PART(table1.email,'@',1) AS table1_username,SPLIT_PART(table2.email,1) AS table2_username,2) AS table1_domain,2) AS table2_domain 
    FROM 
      table1 CROSS 
      JOIN table2
  ) S 
WHERE 
  (
    table1_username = table2_username 
    AND (
      table1_domain like '%.' || table2_domain 
      OR table2_domain like '%.' || table1_domain
    )
  );