sql >> Databasteknik >  >> RDS >> Mysql

Hur kan jag välja liknande rader i två olika tabeller i MySQL (är det möjligt?)

För en UDF-implementering av Levenshtein Distance algoritm du kanske vill kolla in "codejanitor.com:Levenshtein Distance som en MySQL-lagrad 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

Låt oss nu bygga ett testfall med hjälp av informationen du angav i din fråga:

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');

Sedan:

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

Returnerar uppenbarligen en matchning där skolnamnen matchar exakt:

+---------------------+-------------+
| 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)

Nu kan vi försöka använda LEVENSHTEIN funktion för att returnera skolnamn som har ett redigeringsavstånd med 2 tecken eller mindre:

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)

Använder nu <= 3 som en redigeringsavståndströskel:

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

Vi får följande resultat:

+---------------------+--------------+
| 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)

Notera hur den här gången Olde School matchade också Other School och New School matchade Olde School också. Dessa är förmodligen falska positiva och visar att det är mycket viktigt att definiera tröskeln för att undvika felaktiga matchningar.

En vanlig teknik för att ta itu med detta problem är att ta hänsyn till längden på strängarna när man tillämpar en tröskel. Faktum är att webbplatsen som Jag citerade för denna implementering tillhandahåller även en LEVENSHTEIN_RATIO funktion som returnerar förhållandet (i procent) av redigeringsskillnaden baserat på längden på strängarna.



  1. Förstå SQL Server-säkerhetsfunktionen HAS_Permis_BY_Name och dess användningsfall

  2. Krävs nyckelordet "som" i Oracle för att definiera ett alias?

  3. Trimmar inte MySQL TRIM-funktionen radbrytningar eller vagnretur?

  4. Hur man uppdaterar en kolumn baserat på en annan kolumn i SQL