Как я могу использовать нечеткую группировку в запросе MySQL

0

Возможно ли это? Кажется, я не могу найти подходящего руководства для его настройки. Все, что я нахожу, дается с инструкцией по SISS, с которой я вообще не знаком. Другие варианты, которые я нахожу, включают SOUNDEX(), который не имеет отношения к тому, что я хочу делать, поскольку язык данных не является английским.

Я добавлю некоторую информацию о том, чего хочу добиться:

Я пытаюсь найти дубликаты в базе данных, но они не являются дубликатами полного совпадения. Я могу сделать это после извлечения всех записей из моей базы данных с помощью php и levenshtein(), но этот метод очень мало масштабируется, так как он требует прохождения каждой записи и сопоставления ее со всеми непроверенными записями - поэтому я заканчиваю (records.length)! количество минимальных шагов, которые неэффективны.

Я бы хотел, чтобы сравнение в реальном SQL-запросе было более эффективным и могло запускать этот тест дубликатов в крупномасштабной базе данных (более 100 000 записей).

Я чувствую, что образцы кода не имеют отношения к этому вопросу, поэтому не добавляйте их, дайте мне знать, если я должен добавить что-то конкретное.

  • 0
    Как вы ожидаете, что мы предложим какое-либо решение, если мы даже не знаем, чего вы пытаетесь достичь? Существует несколько различных способов нечеткого сопоставления от простых алгоритмов до сложных. Что из этого я должен предложить, я понятия не имею, потому что ваш вопрос не дает никаких подсказок.
Теги:
fuzzy-comparison

1 ответ

3

вы можете создать функцию levenshtein и использовать кросс-соединение

select 
t1.id,t2.id,
levenshtein(t1.action_date,t2.action_date) as levenshtein
from yourTable t1
CROSS join yourTable t2 on t1.id <> t2.id;

функция левенштейна

 DELIMITER //

CREATE DEFINER='root'@'localhost' FUNCTION 'levenshtein'( s1 varchar(255), s2 varchar(255) ) RETURNS int(11)
    DETERMINISTIC
BEGIN 
  DECLARE s1_len, 
    s2_len, 
    i, 
    j, 
    c, 
    c_temp, 
    cost          int; 
  declare s1_char char; 
  -- max strlen=255 
  declare cv0, 
    cv1 varbinary(256); 
  set s1_len = char_length(s1), 
    s2_len = char_length(s2), 
    cv1 = 0x00, 
    j = 1, 
    i = 1, 
    c = 0; 
  if s1 = s2 THEN 
  RETURN 0; 
elseif s1_len = 0 THEN 
  RETURN s2_len; 
elseif s2_len = 0 THEN 
  RETURN s1_len; 
  else 
  WHILE j <= s2_len do 
  SET cv1 = concat(cv1, unhex(hex(j))), 
    j = j + 1; 
end WHILE;
WHILE i <= s1_len do 
SET s1_char = substring(s1, i, 1), 
  c = i, 
  cv0 = unhex(hex(i)), 
  j = 1;WHILE j <= s2_len do 
SET c = c + 1;IF s1_char = Substring(s2, j, 1) then 
SET cost = 0; 
else 
SET cost = 1;END IF;SET c_temp = conv(hex(substring(cv1, j, 1)), 16, 10) + cost;IF c > c_temp then
SET c = c_temp;END IF;SET c_temp = conv(hex(substring(cv1, j+1, 1)), 16, 10) + 1;IF c > c_temp then
SET c = c_temp;END IF;SET cv0 = concat(cv0, unhex(hex(c))), 
  j = j + 1;END WHILE;SET cv1 = cv0, 
  i = i + 1;END WHILE;END IF;RETURN c;
END;//

DELIMITER ;

эта функция не от меня. см.: Как добавить функцию levenshtein в mysql?

образец

MariaDB [test]> select * from yourTable;
+----+-------------+-------------+---------------------+-------------+
| id | ministry_id | building_id | action_date         | action_type |
+----+-------------+-------------+---------------------+-------------+
|  1 |          14 |        1653 | 2011-12-23 11:22:33 |           1 |
|  2 |          14 |        1653 | 2012-02-29 11:51:12 |           2 |
|  3 |          14 |        1653 | 2013-06-25 11:29:22 |           1 |
|  4 |          14 |        1653 | 2017-05-15 17:01:37 |           2 |
+----+-------------+-------------+---------------------+-------------+
4 rows in set (0.00 sec)

MariaDB [test]> select 
    -> t1.id,t2.id,
    -> levenshtein(t1.action_date,t2.action_date) as levenshtein
    -> from yourTable t1
    -> CROSS join yourTable t2 on t1.id <> t2.id;
+----+----+-------------+
| id | id | levenshtein |
+----+----+-------------+
|  2 |  1 |           7 |
|  3 |  1 |           7 |
|  4 |  1 |           9 |
|  1 |  2 |           7 |
|  3 |  2 |           6 |
|  4 |  2 |           8 |
|  1 |  3 |           7 |
|  2 |  3 |           6 |
|  4 |  3 |           8 |
|  1 |  4 |           9 |
|  2 |  4 |           8 |
|  3 |  4 |           8 |
+----+----+-------------+
12 rows in set (0.09 sec)

MariaDB [test]> 
  • 0
    Но где я могу создать функцию? Это то, что я не понимаю. Где ты это положил?
  • 0
    @ CodeAt30 - выберите базу данных с использованием вашей базы данных ; затем скопируйте мою функцию из разделителя // в разделитель; и выполнить их. Вы должны сделать это только один раз. После этого вы можете использовать функцию

Ещё вопросы

Сообщество Overcoder
Наверх
Меню