查询SQL数据库中的交换列

时间:2015-10-07 14:01:57

标签: sql postgresql

我们有一些人以姓氏名字进入姓氏,反之亦然。所以我试图提出一个SQL搜索来匹配交换列。例如,某人可能偶然输入了first_name = Smith, last_name = John的记录。之后,另一个人可能会看到John Smith不在数据库中并输入新用户first_name = John, last_name = Smith,而实际上它是同一个人。

我使用此查询来缩小搜索范围:

SELECT person_id, first_name, last_name
FROM people
WHERE first_name IN (
    SELECT last_name FROM people
) AND last_name IN (
    SELECT first_name FROM people
);

但如果我们有名叫约翰艾伦,艾伦史密斯和史密斯约翰的人,他们都会被归还,即使这些都不是真的重复。在这种情况下,它实际上足够好,我可以在我的特定数据集中看到重复项,但我想知道是否有更精确的方法来执行此操作。

2 个答案:

答案 0 :(得分:1)

我会像这样自我加入:

SELECT p1.person_id, p1.first_name, p1.last_name
FROM people p1
join people p2 on p1.first_name = p2.last_name and p1.last_name = p2.first_name

要在名字上找到拼写错误,我建议:

SELECT p1.person_id, p1.first_name, p1.last_name
FROM people p1
join people p2 on soundex(p1.first_name) = soundex(p2.last_name) and
                  soundex(p1.last_name) = soundex(p2.first_name)

soundex是一个简洁的函数,它以一种两个听起来相同的单词得到相同散列的方式“散列”单词。这意味着Anne和Ann将拥有相同的soundex。所以如果你有一个安妮史密斯和一个史密斯安,上面的查询就会发现它们是匹配的。

答案 1 :(得分:0)

有趣。这是我在使用SQL和Excel的数据分析中所涉及的问题(注意:我很少在我的答案或评论中提及书籍)。

这个想法是总结数据以获得不匹配的可能性。因此,请查看名称作为名字和姓氏出现的次数,然后将这些名称组合起来。所以:

with names as (
      select first_name as name, 1.0 as isf, 0.0 as isl
      from people
      union all
      select last_name, 0, 1
      from people
     ),
     nl as (
      select name, sum(isf) as numf, sum(isl) as numl,
             avg(isf) as p_f, avg(isl) as p_l
      from names
      group by name
     )
select p.*
from people p join
     nl nlf
     on p.first_name = nlf.name join
     nl nll
     on p.last_name = nll.name
order by (coalesce(nlf.p_l, 0) + coalesce(nll.p_f, 0));

这通过一系列名称不匹配的方式对记录进行排序 - 这是姓氏使用的名字和作为名字的姓氏的概率之和。