sql >> Database >  >> RDS >> Mysql

Hoe kan ik vergelijkbare rijen SELECTEREN in twee verschillende tabellen in MySQL (is dat mogelijk?)

Voor een UDF-implementatie van de Levenshtein Distance algoritme dat je misschien wilt bekijken "codejanitor.com:Levenshtein Distance als een MySQL-opgeslagen functie ":

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

Laten we nu een testcase maken met behulp van de gegevens die u in uw vraag hebt verstrekt:

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

Dan:

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

Geeft duidelijk een overeenkomst terug waarbij de schoolnamen exact overeenkomen:

+---------------------+-------------+
| 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 kunnen we proberen de LEVENSHTEIN . te gebruiken functie om schoolnamen terug te geven die een afstand bewerken hebben van 2 tekens of minder:

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)

Gebruikt nu <= 3 als drempel voor bewerkingsafstand:

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

We krijgen het volgende resultaat:

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

Let op hoe deze keer Olde School kwam ook overeen met Other School , en New School kwam overeen met Old School ook. Deze zijn waarschijnlijk vals-positief en laten zien dat het definiëren van de drempel erg belangrijk is om onjuiste overeenkomsten te voorkomen.

Een veelgebruikte techniek om dit probleem aan te pakken is om rekening te houden met de lengte van de snaren bij het toepassen van een drempel. In feite is de site die Ik heb geciteerd voor deze implementatie biedt ook een LEVENSHTEIN_RATIO functie die de verhouding (als een percentage) van het bewerkingsverschil retourneert op basis van de lengte van de tekenreeksen.



  1. Benieuwd naar de nieuwste Microsoft Access-functies?

  2. MySQL - Hoe in te voegen in meerdere tabellen met externe sleutels

  3. SQL SELECT LIKE (ongevoelige hoofdletters)

  4. SQLite - Gegevens invoegen