2012-02-22 14 views
5

El escenario es que tengo una base de datos voluminosos de alrededor de 500.000 registros que tienen dirección de y campo ciudad en el que no hay tal forma estándar de insertar el valor de modo múltiple usuarios, por ejemplo, algunos han insertado su valor ciudad como Bangalore y otro han insertado su ciudad valor como begaluru o benglore (mal escrito)Consulta del registro de base de datos para el valor de cadena coincidente casi similar

también en caso de dirección de campo mismo uso r con registro múltiple ha insertado sus valores de dirección, pero los valores no son exactamente los mismos, por ejemplo, Mountville park Thomas gate y Montlee park thonas gte.

necesito a buscar todos aquellos registro están teniendo los mismos valores y casi similares (de alguna manera missplelled) de dirección de y ciudad.

¿Hay alguna manera de obtener esos registros con valores casi similares pero sin igual?

Gracias.

Respuesta

2

Será una consulta caro, pero como este se espera que sea una operación de una sola vez, es posible considere buscar en una fórmula Levenshtein distance.

Para evitar la necesidad de calcular la distancia para un producto cartesiano de su mesa, primero puede reducir el conjunto de ciudades y direcciones para compararlas con un control de cordura más rápido ... como que comienzan con la misma letra y tienen una longitud similar.

A continuación, podría empezar por devolver solamente los registros con una muy pequeña distancia Levenshtein, y luego aumentar gradualmente la distancia hasta que empiece a tener demasiados falsos positivos.

Here's an implementation directly in MySql:

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

Esta función podría ser utilizado en AA función auxiliar de la siguiente manera:

CREATE FUNCTION levenshtein_ratio(s1 VARCHAR(255), s2 VARCHAR(255)) 
    RETURNS INT 
    DETERMINISTIC 
    BEGIN 
    DECLARE s1_len, s2_len, max_len INT; 
    SET s1_len = LENGTH(s1), s2_len = LENGTH(s2); 
    IF s1_len > s2_len THEN 
     SET max_len = s1_len; 
    ELSE 
     SET max_len = s2_len; 
    END IF; 
    RETURN ROUND((1 - LEVENSHTEIN(s1, s2)/max_len) * 100); 
    END; 

También podría optimizar la función levenshtein pasando en su distancia máxima actual ... si la función supera esa distancia, salga sin calcular la distancia exacta.

0

Ouch. Esto es complicado. Independientemente del método que use, terminará con una consulta muy costosa. Mi recomendación es que escriba una aplicación que duplique los datos en una nueva tabla después de ejecutarla a través de un corrector ortográfico. También puede implementar la consulta en Java, leyendo cada registro, revisando la ortografía del campo y comparándolo.

Afortunadamente, ya existe un software de correctores ortográficos ... Puede echar un vistazo a Jazy o JOrtho para este fin.

0

SOUNDEX() puede ser de uso limitado para usted, sin embargo, sé por experiencia en la normalización de nombres de hoteles en todo el mundo (problema similar con problemas de traducción errónea) que una solución confiable será muy difícil de crear.

La mejor opción habría consistido en hacer una ciudad estándar y/o una lista de direcciones. No tengo idea si algo equivalente al archivo de dirección de código postal (http://www.royalmail.com/marketing-services/address-management-unit/address-data-products/postcode-address-file-paf) que está disponible en el Reino Unido está presente para su localidad. Sin embargo, esto no servirá para normalizar sus datos existentes.

En última instancia, cualquier opción disponible requerirá una gran cantidad de recursos humanos para garantizar que las normalizaciones no coincidan falsamente.

En la primera instancia Me gustaría basarme en los códigos de área que tiene disponibles para usted (¿Google me dice que en India esto es un código PIN?). Probablemente haya bases de datos disponibles que pueden asignar estos códigos a áreas (http://www.geopostcodes.com/india_zip_codes) que eliminarán el problema de normalizar áreas más amplias (suponiendo que su código PIN sea correcto)

En cuanto a la normalización del nivel de calle, es posible que deba Mire SOUNDEX() o algún tipo de sistema arbitrario si desea normalizar los errores ortográficos/diferencias en la forma en que las personas escriben nombres de calles o lugares individuales.

0

Depende del idioma que se está utilizando, por ejemplo, puede quitar las vocales antes de cuerdas que comparan

0

Puede crear una tabla y utilizarla para ayudar en la búsqueda

CREATE TABLE `correct_spelling` (
    correctString varchar(100) not null, 
    variant  varchar(100) not null, 
    primary key (correctString) 
) 

Se podría llenar la tabla con las variantes conocidas (manualmente). Si bien esto suena loco a corto plazo, puede ser la mejor solución a largo plazo. y puede ser reutilizable más tarde en la vida.

Cuestiones relacionadas