Mysql:连接重复的数据,但忽略重复项中的字符串

时间:2018-09-10 19:05:25

标签: mysql sql mysql-5.7 fuzzy-comparison

有没有一种方法可以在忽略给定字符串的同时查找重复数据?

例如,如果我有一个名称表,是否可以串联两个名称均为“ Ann Smith”但忽略字符串“ Dr.”的行。例如,包含“安·史密斯”和“安·史密斯博士”的行应合并为一个名称为“安·史密斯博士”的行。如果名称匹配(减去“ dr。”字符串),并且两行的地址匹配,请连接电话号码。我想取两个名称中的较大者,我认为这将涉及使用MAX语句。

目前,我有一个名为t的表:

name          | phone      | address
ann smith     | 1234567899 | 123 home address
dr. ann smith | 1234567890 | 123 home address
brian smith   | 1235551234 | 789 city street

我想去:

name          | phone                  | address
dr. ann smith | 1234567890, 1234567899 | 123 home address
brian smith   | 1235551234             | 789 city street

3 个答案:

答案 0 :(得分:1)

要执行所需的操作,您可能需要CTE(公用表表达式)和LATERAL查询。不幸的是,MySQL 5.x没有实现它们中的任何一个。

以下查询找到重复的名称:

select plain_name, count(*)
  from (
    select name, trim(replace(lower(name), lower('Dr.'), '')) as plain_name
      from my_table
  ) x
  group by plain_name
  having count(*) > 1

这是朝着正确方向迈出的一步,但是您需要进一步处理才能获得所需的结果。

如果升级到MySQL 8,您将获得CTE,但仍然不会获得LATERAL查询。

编辑:我更进一步地确定了重复的名称。没有CTE,这个查询看起来越来越难看:

select z.*, y.times
  from (
    select name, trim(replace(lower(name), lower('Dr.'), '')) as plain_name
      from my_table
  ) z,
  (
    select plain_name, count(*) as times
      from (
        select name, trim(replace(lower(name), lower('Dr.'), '')) as plain_name
          from my_table
      ) x
      group by plain_name
      having count(*) > 1
  ) y
  where z.plain_name = y.plain_name;

答案 1 :(得分:0)

假设它们是完全嵌套的,则可以通过执行以下操作获得“长格式”:

select name,
       (select t2.name
        from t t2
        where t2.name like concat('%', t.name, '%')
        order by length(t2.name) desc
        limit 1
       ) as long_form
from t;

然后可以在聚合中使用它。我将使用子查询:

select long_form, group_concat(distinct phone) as phones,
       group_concat(distinct address) as addresses
from (select t.*,
             (select t2.name
              from t t2
              where t2.name like concat('%', t.name, '%')
              order by length(t2.name) desc
              limit 1
             ) as long_form
      from t
     ) tt
group by long_from;

答案 2 :(得分:0)

我最终结合了以上答案。首先,我创建了一个临时表来修剪和替换'Dr. '带有空字符串的字符串。

select max(name) as name, group_concat(distinct phone_number) as phone_number, address from temp_names 
    group by plain_name, address having count(*) >=1;

然后,我使用select和group by将该表中的值与相同的plain_name值连接在一起。

name          | phone_number           | address
dr. ann smith | 1234567890, 1234567899 | 123 home address
brian smith   | 1235551234             | 789 city street

这给出了具有所需结果的表:

{{1}}