1

我需要检查一个电子邮件地址是否与另一个电子邮件地址匹配,但可能存在一个错字(例如“hormail”而不是“hotmail”、缺少一封信或多一封信)。

这是一个 postgresql(版本 9.1.4)查询,fuzzymatch 和 levenshtein 都不可用。

4

2 回答 2

2

这是一个起点。这是一个将两封电子邮件分解为 (char-pos, char) 对的函数,然后找到两个输入之间不匹配的对。

CREATE OR REPLACE FUNCTION email_diffs(
    email1 IN text, email2 IN text, 
    chnum OUT integer, ch OUT text, fromwhich OUT integer
) 
RETURNS SETOF RECORD AS $$
BEGIN
    RETURN QUERY
    WITH 
        e1chars AS (
            SELECT generate_series(0, length($1) -1 ) AS chpos, regexp_split_to_table($1,'') ch
        ),
        e2chars AS (
            SELECT generate_series(0, length($2) - 1) AS chpos, regexp_split_to_table($2,'') ch
        ),
        only_in_e1chars AS (
            SELECT * FROM e1chars EXCEPT SELECT * FROM e2chars
        ),
        only_in_e2chars AS (
            SELECT * FROM e2chars EXCEPT SELECT * FROM e1chars
        ),
        mismatched_pairs AS (
            SELECT *, 1 FROM only_in_e1chars UNION SELECT *, 2 FROM only_in_e2chars
        )
    SELECT * FROM mismatched_pairs;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;

结果如下所示:

regress=# SELECT * FROM email_diffs('fred@bo','fred@bob');
 chnum | ch | fromwhich 
-------+----+-----------
     7 | b  |         2
(1 row)

regress=# SELECT * FROM email_diffs('fred@bob','fred@bbo');
 chnum | ch | fromwhich 
-------+----+-----------
     6 | b  |         2
     6 | o  |         1
     7 | b  |         1
     7 | o  |         2
(4 rows)

您应该能够使用另一个 CTE 来调用它,该 CTE 测试您感兴趣的每个错误,或者只是在该主函数中扩展 CTE,并使用附加子句来测试每种情况并返回判断。

究竟如何做到这一点将取决于您必须测试的规则的细节以及您对准确检测一个错字的严格程度。你没有具体说明。


e1chars您可能已经注意到在and中使用不带 FROM 子句的 SELECT 看起来很奇怪e2chars,其中在 SELECT 列表中调用了两个函数。这是一个非常奇怪的对 SQL 的 PostgreSQL 扩展,您通常不应该使用它,因为结果通常不是您所期望的。PostgreSQL 将支持LATERAL9.3 中的 SQL 标准语法,应该优先使用它。

于 2012-08-31T13:39:44.037 回答
0

你应该使用fuzzystrmatch 和/或pg_trgm Postgres 扩展。您可以通过运行来启用这些:

$ psql mydb
mydb=# CREATE EXTENSION fuzzystrmatch;
mydb=# CREATE EXTENSION pg_trgm;

然后,您可以执行如下查询:

mydb=# SELECT email from Users where email % 'hormail' or difference(email, 'hormail') > 2;
于 2012-10-02T15:30:54.393 回答