2008-08-08 25 views
5

Me han entregado una tabla con aproximadamente 18000 filas. Cada registro describe la ubicación de un cliente. El problema es que cuando la persona creó la tabla, no agregaron un campo para "Nombre de la compañía", solo "Nombre de la ubicación", y una empresa puede tener muchas ubicaciones.Normalización de una tabla con baja integridad

Por ejemplo, aquí hay algunos registros que describen el mismo cliente:

Localización Tabla

ID Location_Name  
1 TownShop#1   
2 Town Shop - Loc 2 
3 The Town Shop  
4 TTS - Someplace 
5 Town Shop,the 3 
6 Toen Shop4   

Mi objetivo es hacer que parezca:

Localización Tabla

ID Company_ID Location_Name  
1 1   Town Shop#1  
2 1   Town Shop - Loc 2 
3 1   The Town Shop  
4 1   TTS - Someplace 
5 1   Town Shop,the 3 
6 1   Toen Shop4   

Company Tabla

Company_ID Company_Name 
1   The Town Shop 

No hay una mesa "Compañía", que tendrá que generar la lista Nombre de la empresa desde el más descriptivo o mejor Lugar Nombre que representa las múltiples ubicaciones.

Actualmente estoy pensando que necesito generar una lista de nombres de ubicación que sean similares, y luego revisar esa lista a mano.

Se agradece cualquier sugerencia sobre cómo puedo abordar esto.

@Neall, gracias por su declaración, pero desafortunadamente, cada nombre de ubicación es distinto, no hay nombres de ubicación duplicados, solo similares. Entonces, en los resultados de su extracto "reccount" es 1 en cada fila.

@yukondude, Su paso 4 es el corazón de mi pregunta.

Respuesta

0

Actualice la pregunta, ¿tiene una lista de CompanyNames disponible para usted? Lo pregunto porque quizás puedas utilizar Levenshtein algo para encontrar una relación entre tu lista de CompanyNames y LocationNames.


actualización

No hay una lista de los nombres de compañías, voy a tener que generar el nombre de la empresa desde el más descriptivo o mejor Lugar Nombre que representa las múltiples ubicaciones.

bien ... prueba esto:

  1. construir una lista de candidatos CompanyNames encontrando LocationNames compone en su mayoría o todos los caracteres alfabéticos. Puede usar regular expressions para esto. Almacene esta lista en una tabla separada.
  2. Ordene esa lista alfabéticamente y (manualmente) determine qué entradas deben ser CompanyNames.
  3. Compare cada CompanyName con cada LocationName y obtenga una puntuación de coincidencia (use Levenshtein o algún otro algoritmo de coincidencia de cadenas). Almacene el resultado en una tabla separada.
  4. Establezca una puntuación de umbral tal que cualquier Umbral de MatchScore < no se considerará una coincidencia para un determinado CompanyName.
  5. Examine manualmente a través de LocationNames by CompanyName | LocationName | MatchScore, y averigüe cuáles coinciden realmente. Ordenar por MatchScore debería hacer que el proceso sea menos doloroso.

El objetivo de las acciones anteriores es automatizar las piezas y limitar el alcance de su problema. Está lejos de ser perfecto, pero con suerte le ahorrará la molestia de pasar por 18K registros a mano.

1

He tenido que hacer esto antes. La única forma real de hacerlo es hacer coincidir manualmente las distintas ubicaciones. Use la interfaz de la consola de su base de datos y agrupe las declaraciones seleccionadas. Primero, agregue su campo "Nombre de la compañía". Entonces:

SELECT count(*) AS repcount, "Location Name" FROM mytable 
WHERE "Company Name" IS NULL 
GROUP BY "Location Name" 
ORDER BY repcount DESC 
LIMIT 5; 

averiguar qué compañía de la ubicación en la parte superior de la lista pertenece y luego actualizar el campo de nombre de la empresa con un UPDATE ... WHERE "Lugar Nombre" = "El Lugar" comunicado.

P.S. - Realmente debe dividir los nombres de su empresa y de su ubicación en tablas separadas y referirse a ellos por sus claves principales.

Actualización: - Wow - no hay duplicados? ¿Cuántos registros tienes?

0

Iba a recomendar algún algoritmo de coincidencia de tokens complicado pero es muy complicado hacerlo bien y si los datos no tienen mucha correlación (errores tipográficos, etc.), entonces no van a dar muy buenos resultados.

Le recomendaría que envíe un trabajo al Amazon Mechanical Turk y deje que un ser humano lo resuelva.

0

Idealmente, probablemente querría una tabla separada llamada Company y luego una columna company_id en esta tabla de "Ubicación" que es una clave externa a la clave principal de la tabla Company, probablemente llamada id. Eso evitaría un poco de duplicación de texto en esta tabla (más de 18,000 filas, una clave externa entera ahorraría bastante espacio sobre una columna varchar).

Pero todavía tiene que enfrentarse con un método para cargar esa tabla de Compañía y luego asociarla adecuadamente con las filas en Ubicación. No hay una solución general, pero podría hacer algo en este sentido:

  1. Cree la tabla Company, con una columna de identificación que se autoincrementa (depende de su RDBMS).
  2. Encuentre todos los nombres únicos de compañías e insértelos en la empresa.
  3. Agregue una columna, company_id, a la ubicación que acepta valores NULL (por ahora) y que es una clave externa de la columna Company.id.
  4. Para cada fila en Ubicación, determine la compañía correspondiente y ACTUALICE la columna company_id de esa fila con la identificación de esa compañía. Este es probablemente el paso más desafiante. Si sus datos son similares a los que muestra en el ejemplo, es probable que tenga que realizar muchas pruebas con varios enfoques de correspondencia de cadenas.
  5. Una vez que todas las filas en Ubicación tienen un valor company_id, puede ALTERAR la tabla Company para agregar una restricción NOT NULL a la columna company_id (suponiendo que cada ubicación debe tener tener una empresa, lo que parece razonable).

Si puede hacer una copia de su tabla Ubicación, puede construir gradualmente una serie de sentencias SQL para llenar la clave externa company_id. Si comete un error, puede comenzar nuevamente y volver a ejecutar el script hasta el punto de falla.

0

Sí, ese paso 4 de mi publicación anterior es un juego de niños.

No importa qué, probablemente tenga que hacer algo de esto a mano, pero es posible que pueda automatizar la mayor parte. Para las ubicaciones de ejemplo que diste, una consulta como la siguiente fijaría el valor Company_id apropiado:

UPDATE Location 
SET  Company_ID = 1 
WHERE (LOWER(Location_Name) LIKE '%to_n shop%' 
OR  LOWER(Location_Name) LIKE '%tts%') 
AND  Company_ID IS NULL; 

Creo que habría que coincida con sus ejemplos (añadí la parte IS NULL para no sobrescribir establecido previamente los valores Company_id), sino de Por supuesto, en 18,000 filas tendrás que ser muy inventivo para manejar las diversas combinaciones.

Otra cosa que podría ayudar sería utilizar los nombres en la empresa para generar consultas como la de arriba. Usted podría hacer algo como lo siguiente (en MySQL):

SELECT CONCAT('UPDATE Location SET Company_ID = ', 
     Company_ID, ' WHERE LOWER(Location_Name) LIKE ', 
     LOWER(REPLACE(Company_Name), ' ', '%'), ' AND Company_ID IS NULL;') 
FROM Company; 

Luego simplemente ejecute las instrucciones que produce. Eso podría hacer mucho del trabajo grunge para ti.

Cuestiones relacionadas