Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie kann ich ähnliche Zeilen in zwei verschiedenen Tabellen in MySQL auswählen (ist das möglich?)

Für eine UDF-Implementierung der Levenshtein Distance Algorithmus, den Sie vielleicht ausprobieren möchten "codejanitor.com:Levenshtein-Distanz als gespeicherte MySQL-Funktion ":

CREATE FUNCTION LEVENSHTEIN (s1 VARCHAR(255), s2 VARCHAR(255))
RETURNS INT
DETERMINISTIC
BEGIN
  DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
  DECLARE s1_char CHAR;
  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

Lassen Sie uns nun einen Testfall erstellen, indem Sie die Daten verwenden, die Sie in Ihrer Frage angegeben haben:

CREATE TABLE table_a (name varchar(20));
CREATE TABLE table_b (name varchar(20));

INSERT INTO table_a VALUES('Olde School');      
INSERT INTO table_a VALUES('New School');
INSERT INTO table_a VALUES('Other, C.S. School');
INSERT INTO table_a VALUES('Main School');
INSERT INTO table_a VALUES('Too Cool for School');

INSERT INTO table_b VALUES('Old School');
INSERT INTO table_b VALUES('New ES');
INSERT INTO table_b VALUES('Other School');
INSERT INTO table_b VALUES('Main School');
INSERT INTO table_b VALUES('Hardknocks School');

Dann:

SELECT     *
FROM       table_a a
LEFT JOIN  table_b b ON (a.name = b.name);

Gibt offensichtlich eine Übereinstimmung zurück, bei der die Schulnamen genau übereinstimmen:

+---------------------+-------------+
| name                | name        |
+---------------------+-------------+
| Olde School         | NULL        |
| New School          | NULL        |
| Other, C.S. School  | NULL        |
| Main School         | Main School |
| Too Cool for School | NULL        |
+---------------------+-------------+
5 rows in set (0.00 sec)

Jetzt können wir versuchen, den LEVENSHTEIN zu verwenden Funktion, um Schulnamen zurückzugeben, die eine Bearbeitungsentfernung haben von 2 Zeichen oder weniger:

SELECT     *
FROM       table_a a
LEFT JOIN  table_b b ON (LEVENSHTEIN(a.name, b.name) <= 2);

+---------------------+-------------+
| name                | name        |
+---------------------+-------------+
| Olde School         | Old School  |
| New School          | NULL        |
| Other, C.S. School  | NULL        |
| Main School         | Main School |
| Too Cool for School | NULL        |
+---------------------+-------------+
5 rows in set (0.08 sec)

Jetzt mit <= 3 als Entfernungsschwelle bearbeiten:

SELECT     *
FROM       table_a a
LEFT JOIN  table_b b ON (LEVENSHTEIN(a.name, b.name) <= 3);

Wir erhalten das folgende Ergebnis:

+---------------------+--------------+
| name                | name         |
+---------------------+--------------+
| Olde School         | Old School   |
| Olde School         | Other School |
| New School          | Old School   |
| Other, C.S. School  | NULL         |
| Main School         | Main School  |
| Too Cool for School | NULL         |
+---------------------+--------------+
6 rows in set (0.06 sec)

Beachten Sie, wie diesmal Olde School stimmte auch mit Other School überein , und New School passend zu Old School auch. Diese sind wahrscheinlich falsch positiv und zeigen, dass die Definition des Schwellenwerts sehr wichtig ist, um falsche Übereinstimmungen zu vermeiden.

Eine übliche Technik, um dieses Problem anzugehen, besteht darin, die Länge der Saiten beim Anwenden eines Schwellenwerts zu berücksichtigen. Tatsächlich ist die Site, die Ich habe für diese Implementierung zitiert stellt auch ein LEVENSHTEIN_RATIO bereit Funktion, die das Verhältnis (als Prozentsatz) der Bearbeitungsdifferenz basierend auf der Länge der Zeichenfolgen zurückgibt.