如何使用多个条件识别MySQL表中的唯一人员

时间:2011-08-18 13:45:32

标签: mysql select unique

我有一个〜200k记录表dat的人,他们的识别数据以及测试日期和结果,这里是虚拟版本:

+----+---------+----------+------------+----------+------------+--------+
| id | surname | forename | dob        | SchoolID | testDate   | result |
+----+---------+----------+------------+----------+------------+--------+
|  1 | Smith   | Mary     | 1980-04-11 | NULL     | 2005-10-12 |  14.32 |
|  2 | Smith   | Mary     | 1980-04-11 | 1234     | 2007-03-02 |   18.1 |
|  3 | Jones   | Kim      | 1978-10-24 | 4657     | 2002-04-14 |  24.31 |
|  4 | Jones   | Kim      | NULL       | 4567     | 2002-10-08 |  19.02 |
|  5 | Roberts | Kim      | 1978-10-24 | 4567     | 2003-12-18 |  14.19 |
|  6 | Roberts | Kim      | 1978-10-24 | 4567     | 2005-02-11 |  18.26 |
+----+---------+----------+------------+----------+------------+--------+

我想确定有多个测试的人,并创建一个新列uniqueID,为独特的人提供新的ID。遗憾的是,我的数据库不是很整洁所以我需要使用几个标准将这些记录分成独特的个体:

  • 姓氏,forename和dob是相同的(因为SchoolID经常缺失或错误)
  • 姓氏,姓氏和学校ID是相同的(因为D.O.B.有时不输入,或 输错了)
  • forename,dob和SchoolID是相同的(人们有时会结婚)

在上面的例子中,Mary Smith和Kim Roberts nee Jones表中只有两个独特的人,所以这个uniqueID列应该最终成为:

+----+----------+
| id | uniqueID |
+----+----------+
|  1 |        1 |
|  2 |        1 |
|  3 |        2 |
|  4 |        2 |
|  5 |        2 |
|  6 |        2 |
+----+----------+

虽然我已经习惯了几年MySQL,但我仍然是初学者。我已经搜索并尝试了几天,到目前为止我已经设法了:

SELECT surname, forename, SchoolID 
   FROM dat 
   GROUP BY CONCAT(surname, forename, SchoolID);

这是第二个标准,例如,(我计划在新表中提供一个自动递增键,然后作为唯一ID重新加入),但我对这些多重标准不满意,所以任何帮助都非常赞赏!

由于 尼克

2 个答案:

答案 0 :(得分:0)

你试过“SELECT distinct”吗?

答案 1 :(得分:0)

你可以通过自我加入来做到这一点。不过,我会分多步进行 - 从最好的到最弱的比赛。

因此,假设schoolID在存在时是可靠的,这就是你找到重复项的方法:

select *
from   dat parent, 
       dat child
where  parent.id      <> child.id
and    parent.schoolid =  child.schoolid

(对于antediluvian连接语法的道歉)。

运行它,看看你是否有任何奇怪之处;如果你喜欢它,把它变成一个更新。使用自联接的更新在MySQL中有点痛苦,最简单的方法是创建一个要加入的视图。

create view dupes as

select   min(parent.id) as uniqueid, child.id
from     dat parent, 
         dat child
where    parent.schoolid =  child.schoolid
group by child.id

update  ignore dat, dupes
set     dat.uniqueid =   dupes.uniqueid
where    dat.id      = dupes.id

现在,你进入第二个最强的链接,例如:

    select *
    from   dat parent, 
           dat child
    where  parent.id      <> child.id
    and    parent.uniqueID is  null
    and    child.uniqueID  is  null
    and    parent.forename = child.forename
    and    parent.surname  = child.surname
    and    parent.dob      = child.dob

再次,运行它,检查数据是否有奇怪,变成更新语句。

接下来,放宽限制 - 如果我们之前已将父级与另一条记录匹配,那也没关系,所以我们可以删除对null的检查:

select *
from   dat parent, 
       dat child
where  parent.id      <> child.id
and    child.uniqueID  is  null
and    parent.forename = child.forename
and    parent.surname  = child.surname
and    parent.dob      = child.dob

等等,等等。 通过最强烈的可能性下降,你可以降低相当脆弱的相似性的风险,从而超越明确的联系(例如,两个名叫“Kim”的人,恰好出生于1978-10-24,

首先运行选择,然后再将其转换为更新,可以避免人为错误。