如何在同一个表中找到类似的记录?

时间:2014-02-25 20:45:38

标签: mysql

我有一个调度数据库,我想找到一种方法来选择所有类似的未来约会,因为我们有很多客户自己预订。我一直在寻找,但我无法找到一种方法来做我想做的事。

例如,如果我有以下行,我希望能够选择具有相同语言的行,相隔15分钟的时间,以及共享>的名称。 70%的相同角色。

   |Rec_id|Date_time       |Language|App_name |
   |1     |2014-03-15 12:40|Spanish |Ricardo  |
   |2     |2014-03-15 12:45|Spanish |Ricerdu  |
   |3     |2014-03-16 12:45|Tongan  |Tuaffu   |
   |4     |2014-03-17 12:45|Korean  |Kim      |
   |5     |2014-03-18 12:45|German  |Biternof |
   |6     |2014-03-18 12:32|German  |Biterknof|

根据以上数据,我需要的记录是1,2,5和6。

2 个答案:

答案 0 :(得分:1)

我想到的第一件事是Levenshtein,但由于MySQL没有本机支持,事情变得更加复杂。

这个解决方案没有经过优化或是最好的解决方案,但我应该开展工作。

  • 我会创建一个新列,我们称之为“Duplicate_for”,DEFAULT NULL。
  • 我会创建一个触发器:在此表的INSERT前进行TRIGGER。
  • 我会创建一个函数来计算两个字符串的Levenshtein距离。
  • 我会将TRIGGER和Levenshtein与以下查询结合起来。

触发+查询本身:

DELIMITER //
CREATE TRIGGER `booking_before_insert` BEFORE INSERT ON `booking` FOR EACH ROW BEGIN
    DECLARE existingId INT(10) DEFAULT NULL;

    SELECT 
        MAX(id) 
    INTO 
        existingId
    FROM 
        booking 
    WHERE   
        booking.dirty_id IS NULL AND
        booking.lang = NEW.lang AND
        booking.created >= DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND 
        (LEVENSHTEIN(booking.name, NEW.name) / LENGTH(booking.name)) < 0.3;

    SET NEW.dirty_id = existingId;
END//
DELIMITER ;

您可以从以下网址了解有关Levenshtein的更多信息:

现在,您可以使用Duplicate_for检测重复项。

答案 1 :(得分:0)

这是一个很好的问题。让我在夜晚醒来很长时间......:D:D 首先,您不需要任何触发器和/或额外行来解决此问题。

这是我到目前为止所尝试的。

SELECT
t3.*
FROM
Table1 t1
INNER JOIN
Table1 t2
ON
(
  t2.Rec_id > t1.Rec_id
  AND t2.Language = t1.Language
  AND ABS( TIMESTAMPDIFF(MINUTE, t1.Date_time, t2.Date_time)) <= 15
  #AND (
  #  SOUNDEX( t1.App_name ) LIKE CONCAT(TRIM(TRAILING '0' FROM SOUNDEX( t2.App_name )), '%') 
  #  OR
  #  SOUNDEX( t2.App_name ) LIKE CONCAT(TRIM(TRAILING '0' FROM SOUNDEX( t1.App_name )), '%')
  #)
)
INNER JOIN
Table1 t3
ON( t1.Rec_id = t3.Rec_id OR t2.Rec_id = t3.Rec_id )
GROUP BY t3.Rec_id

我已经评论了SOUNDEX部分.. 70%匹配是模糊的,不是吗? 尝试取消注释查询的SOUNDEX部分,以检查它是否解决了更大的问题。