【问题标题】:How to identify unique people in a MySQL table using more than one criteria如何使用多个标准识别 MySQL 表中的唯一人员
【发布时间】:2011-08-18 13:45:31
【问题描述】:

我有一个约 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。遗憾的是,我的数据库不是很整齐,所以我需要使用几个标准将这些记录分成不同的个体:

  • 姓、名和出生日期相同(因为 SchoolID 经常丢失或错误)
  • surname、forname 和 SchoolID 相同(因为有时不输入 DOB,或者 输入错误)
  • 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 重新加入),但我对这些多个标准不太了解,因此非常感谢您的帮助!

谢谢 尼克

【问题讨论】:

  • 你们有没有想过将 SS# 添加到表格中以轻松识别人?
  • 这应该是 SchoolID 的用途。可悲的是,在现实生活中它并没有成功,因为经常没有输入,人们被重新发行了新的(甚至同样的号码被多次发行)。
  • 如果有人结婚了,换了一个新姓,你想怎么匹配那个人?

标签: mysql select unique


【解决方案1】:

你试过“SELECT distinct”吗?

【讨论】:

  • 是的——但迄今为止从未成功地结合所有这些不同的标准。它似乎与 GROUP BY 大致相同,即对于一个约束来说很好,但我还没有设法让它完成所有工作。
  • 嗯,既然有不止一个“Kims”,你用 DOB 而不是 schoolID 搜索怎么样?我认为更有可能存在唯一的姓名、姓氏和出生日期,而不是姓名、姓氏和学校 ID。
【解决方案2】:

您可以通过自联接来做到这一点。不过,我会分多个步骤进行 - 从最佳匹配到最弱匹配。

因此,假设 schoolID 在存在时是可靠的,这就是您查找重复项的方式:

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

(为古老的连接语法道歉)。

运行它,看看是否有任何异常;如果你喜欢它,把它变成一个更新。在 MySQL 中使用 self join 进行更新有点痛苦,最简单的方法是创建一个 view 来加入。

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

再次运行它,检查数据是否有异常,然后转换为更新语句。

接下来,放宽限制——如果我们之前已经将父记录匹配到另一条记录就可以了,这样我们就可以取消对空的检查:

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 日,

通过首先运行选择,然后将它们转换为更新,可以避免人为错误。

【讨论】:

  • 您的第一个代码块运行并产生重复项 - 但是第二个块,更新部分,对我不起作用 - 我删除了可能错误的额外时间段,但它返回与“来自”部分...非常感谢,
  • 你是对的——更新在 MySQL 中不起作用。正在努力解决这个问题......
  • 太好了 - 谢谢。新代码现在可以工作了,我已经从输入代码中学到了很多东西!到目前为止,我已经获得了三个不同学校 ID 的唯一 ID,但是,由于唯一 ID 为 NULL(只有一个)的限制,第二个 SELECT 生成了一个空集。消除这些限制似乎对我不起作用,但我会坚持下去!再次感谢!
猜你喜欢
  • 1970-01-01
  • 2012-12-11
  • 2011-12-04
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 2020-04-05
相关资源
最近更新 更多